Bug 1961115 - Pass new_frame_ready parameters via a struct. r=gfx-reviewers,gw

This patch is a preliminary refactoring to make it simpler to pass additional information to the C++ side and should not affect behavior.
In a followup patch the widget glue will have special handling for frames that need to be rendered but not presented.

Differential Revision: https://phabricator.services.mozilla.com/D245564
This commit is contained in:
Nicolas Silva
2025-04-18 12:56:22 +00:00
parent 1a2e198143
commit a7fed60e37
13 changed files with 117 additions and 90 deletions

View File

@@ -437,9 +437,9 @@ void RenderThread::WrNotifierEvent_WakeUp(WrWindowId aWindowId,
PostWrNotifierEvents(aWindowId, info);
}
void RenderThread::WrNotifierEvent_NewFrameReady(WrWindowId aWindowId,
bool aCompositeNeeded,
FramePublishId aPublishId) {
void RenderThread::WrNotifierEvent_NewFrameReady(
WrWindowId aWindowId, wr::FramePublishId aPublishId,
const wr::FrameReadyParams* aParams) {
auto windows = mWindowInfos.Lock();
auto it = windows->find(AsUint64(aWindowId));
if (it == windows->end()) {
@@ -449,7 +449,7 @@ void RenderThread::WrNotifierEvent_NewFrameReady(WrWindowId aWindowId,
WindowInfo* info = it->second.get();
info->mPendingWrNotifierEvents.emplace(
WrNotifierEvent::NewFrameReady(aCompositeNeeded, aPublishId));
WrNotifierEvent::NewFrameReady(aPublishId, aParams));
PostWrNotifierEvents(aWindowId, info);
}
@@ -529,12 +529,12 @@ void RenderThread::HandleWrNotifierEvents(WrWindowId aWindowId) {
auto& front = events->front();
switch (front.mTag) {
case WrNotifierEvent::Tag::WakeUp:
WrNotifierEvent_HandleWakeUp(aWindowId, front.CompositeNeeded());
WrNotifierEvent_HandleWakeUp(aWindowId, front.FrameReadyParams());
handleNext = false;
break;
case WrNotifierEvent::Tag::NewFrameReady:
WrNotifierEvent_HandleNewFrameReady(aWindowId, front.CompositeNeeded(),
front.PublishId());
WrNotifierEvent_HandleNewFrameReady(aWindowId, front.PublishId(),
front.FrameReadyParams());
handleNext = false;
break;
case WrNotifierEvent::Tag::ExternalEvent:
@@ -558,21 +558,21 @@ void RenderThread::HandleWrNotifierEvents(WrWindowId aWindowId) {
}
}
void RenderThread::WrNotifierEvent_HandleWakeUp(wr::WindowId aWindowId,
bool aCompositeNeeded) {
void RenderThread::WrNotifierEvent_HandleWakeUp(
wr::WindowId aWindowId, const wr::FrameReadyParams& aParams) {
MOZ_ASSERT(IsInRenderThread());
bool isTrackedFrame = false;
HandleFrameOneDoc(aWindowId, aCompositeNeeded, isTrackedFrame, Nothing());
HandleFrameOneDoc(aWindowId, aParams, isTrackedFrame, Nothing());
}
void RenderThread::WrNotifierEvent_HandleNewFrameReady(
wr::WindowId aWindowId, bool aCompositeNeeded, FramePublishId aPublishId) {
wr::WindowId aWindowId, wr::FramePublishId aPublishId,
const wr::FrameReadyParams& aParams) {
MOZ_ASSERT(IsInRenderThread());
bool isTrackedFrame = true;
HandleFrameOneDoc(aWindowId, aCompositeNeeded, isTrackedFrame,
Some(aPublishId));
HandleFrameOneDoc(aWindowId, aParams, isTrackedFrame, Some(aPublishId));
}
void RenderThread::WrNotifierEvent_HandleExternalEvent(
@@ -601,7 +601,8 @@ Maybe<layers::FrameRecording> RenderThread::EndRecordingForWindow(
return renderer->EndRecording();
}
void RenderThread::HandleFrameOneDoc(wr::WindowId aWindowId, bool aRender,
void RenderThread::HandleFrameOneDoc(wr::WindowId aWindowId,
const wr::FrameReadyParams& aParams,
bool aTrackedFrame,
Maybe<FramePublishId> aPublishId) {
MOZ_ASSERT(IsInRenderThread());
@@ -610,14 +611,15 @@ void RenderThread::HandleFrameOneDoc(wr::WindowId aWindowId, bool aRender,
return;
}
HandleFrameOneDocInner(aWindowId, aRender, aTrackedFrame, aPublishId);
HandleFrameOneDocInner(aWindowId, aParams, aTrackedFrame, aPublishId);
if (aTrackedFrame) {
DecPendingFrameCount(aWindowId);
}
}
void RenderThread::HandleFrameOneDocInner(wr::WindowId aWindowId, bool aRender,
void RenderThread::HandleFrameOneDocInner(wr::WindowId aWindowId,
const wr::FrameReadyParams& aParams,
bool aTrackedFrame,
Maybe<FramePublishId> aPublishId) {
if (IsDestroyed(aWindowId)) {
@@ -628,7 +630,6 @@ void RenderThread::HandleFrameOneDocInner(wr::WindowId aWindowId, bool aRender,
return;
}
bool render = aRender;
PendingFrameInfo frame;
if (aTrackedFrame) {
// scope lock
@@ -663,7 +664,7 @@ void RenderThread::HandleFrameOneDocInner(wr::WindowId aWindowId, bool aRender,
RendererStats stats = {0};
UpdateAndRender(aWindowId, frame.mStartId, frame.mStartTime, render,
UpdateAndRender(aWindowId, frame.mStartId, frame.mStartTime, aParams,
/* aReadbackSize */ Nothing(),
/* aReadbackFormat */ Nothing(),
/* aReadbackBuffer */ Nothing(), &stats);
@@ -812,14 +813,14 @@ void RenderThread::SetFramePublishId(wr::WindowId aWindowId,
void RenderThread::UpdateAndRender(
wr::WindowId aWindowId, const VsyncId& aStartId,
const TimeStamp& aStartTime, bool aRender,
const TimeStamp& aStartTime, const wr::FrameReadyParams& aParams,
const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<wr::ImageFormat>& aReadbackFormat,
const Maybe<Range<uint8_t>>& aReadbackBuffer, RendererStats* aStats,
bool* aNeedsYFlip) {
AUTO_PROFILER_LABEL("RenderThread::UpdateAndRender", GRAPHICS);
MOZ_ASSERT(IsInRenderThread());
MOZ_ASSERT(aRender || aReadbackBuffer.isNothing());
MOZ_ASSERT(aParams.render || aReadbackBuffer.isNothing());
auto it = mRenderers.find(aWindowId);
MOZ_ASSERT(it != mRenderers.end());
@@ -836,20 +837,22 @@ void RenderThread::UpdateAndRender(
"Paint", markerName.c_str(), geckoprofiler::category::GRAPHICS,
Some(renderer->GetCompositorBridge()->GetInnerWindowId()));
bool render = aParams.render;
if (renderer->IsPaused()) {
aRender = false;
render = false;
}
LOG("RenderThread::UpdateAndRender() aWindowId %" PRIx64 " aRender %d",
AsUint64(aWindowId), aRender);
AsUint64(aWindowId), render);
layers::CompositorThread()->Dispatch(
NewRunnableFunction("NotifyDidStartRenderRunnable", &NotifyDidStartRender,
renderer->GetCompositorBridge()));
wr::RenderedFrameId latestFrameId;
if (aRender) {
latestFrameId = renderer->UpdateAndRender(
aReadbackSize, aReadbackFormat, aReadbackBuffer, aNeedsYFlip, aStats);
if (render) {
latestFrameId = renderer->UpdateAndRender(aReadbackSize, aReadbackFormat,
aReadbackBuffer, aNeedsYFlip,
aParams, aStats);
} else {
renderer->Update();
}
@@ -864,7 +867,7 @@ void RenderThread::UpdateAndRender(
layers::CompositorThread()->Dispatch(
NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender,
renderer->GetCompositorBridge(), info, aStartId,
aStartTime, start, end, aRender, *aStats));
aStartTime, start, end, render, *aStats));
RefPtr<layers::Fence> fence;
@@ -1738,14 +1741,13 @@ void wr_notifier_wake_up(mozilla::wr::WrWindowId aWindowId,
aCompositeNeeded);
}
void wr_notifier_new_frame_ready(mozilla::wr::WrWindowId aWindowId,
bool aCompositeNeeded,
mozilla::wr::FramePublishId aPublishId) {
void wr_notifier_new_frame_ready(wr::WrWindowId aWindowId,
wr::FramePublishId aPublishId,
const wr::FrameReadyParams* aParams) {
auto* renderThread = mozilla::wr::RenderThread::Get();
renderThread->DecPendingFrameBuildCount(aWindowId);
renderThread->WrNotifierEvent_NewFrameReady(aWindowId, aCompositeNeeded,
aPublishId);
renderThread->WrNotifierEvent_NewFrameReady(aWindowId, aPublishId, aParams);
}
void wr_notifier_external_event(mozilla::wr::WrWindowId aWindowId,

View File

@@ -209,7 +209,8 @@ class RenderThread final {
/// Can only be called from the render thread.
void UpdateAndRender(wr::WindowId aWindowId, const VsyncId& aStartId,
const TimeStamp& aStartTime, bool aRender,
const TimeStamp& aStartTime,
const wr::FrameReadyParams& aParams,
const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<wr::ImageFormat>& aReadbackFormat,
const Maybe<Range<uint8_t>>& aReadbackBuffer,
@@ -274,8 +275,8 @@ class RenderThread final {
// RenderNotifier implementation
void WrNotifierEvent_WakeUp(WrWindowId aWindowId, bool aCompositeNeeded);
void WrNotifierEvent_NewFrameReady(WrWindowId aWindowId,
bool aCompositeNeeded,
FramePublishId aPublishId);
wr::FramePublishId aPublishId,
const wr::FrameReadyParams* aParams);
void WrNotifierEvent_ExternalEvent(WrWindowId aWindowId, size_t aRawEvent);
/// Can be called from any thread.
@@ -371,34 +372,41 @@ class RenderThread final {
const Tag mTag;
private:
WrNotifierEvent(const Tag aTag, const bool aCompositeNeeded)
: mTag(aTag), mCompositeNeeded(aCompositeNeeded) {
MOZ_ASSERT(mTag == Tag::WakeUp);
}
WrNotifierEvent(const Tag aTag, bool aCompositeNeeded,
FramePublishId aPublishId)
: mTag(aTag),
mCompositeNeeded(aCompositeNeeded),
mPublishId(aPublishId) {
WrNotifierEvent(const Tag aTag, wr::FramePublishId aPublishId,
wr::FrameReadyParams aParams)
: mTag(aTag), mPublishId(aPublishId), mParams(aParams) {
MOZ_ASSERT(mTag == Tag::NewFrameReady);
}
WrNotifierEvent(const Tag aTag, wr::FrameReadyParams aParams)
: mTag(aTag), mParams(aParams) {
MOZ_ASSERT(mTag == Tag::WakeUp);
}
WrNotifierEvent(const Tag aTag, UniquePtr<RendererEvent>&& aRendererEvent)
: mTag(aTag), mRendererEvent(std::move(aRendererEvent)) {
MOZ_ASSERT(mTag == Tag::ExternalEvent);
}
const bool mCompositeNeeded = false;
const FramePublishId mPublishId = FramePublishId::INVALID;
const wr::FramePublishId mPublishId = wr::FramePublishId::INVALID;
const wr::FrameReadyParams mParams = {
.present = false,
.render = false,
.scrolled = false,
};
UniquePtr<RendererEvent> mRendererEvent;
public:
static WrNotifierEvent WakeUp(const bool aCompositeNeeded) {
return WrNotifierEvent(Tag::WakeUp, aCompositeNeeded);
wr::FrameReadyParams params = {
.present = aCompositeNeeded,
.render = aCompositeNeeded,
.scrolled = false,
};
return WrNotifierEvent(Tag::WakeUp, params);
}
static WrNotifierEvent NewFrameReady(const bool aCompositeNeeded,
const FramePublishId aPublishId) {
return WrNotifierEvent(Tag::NewFrameReady, aCompositeNeeded, aPublishId);
static WrNotifierEvent NewFrameReady(FramePublishId aPublishId,
const wr::FrameReadyParams* aParams) {
return WrNotifierEvent(Tag::NewFrameReady, aPublishId, *aParams);
}
static WrNotifierEvent ExternalEvent(
@@ -406,18 +414,16 @@ class RenderThread final {
return WrNotifierEvent(Tag::ExternalEvent, std::move(aRendererEvent));
}
bool CompositeNeeded() {
if (mTag == Tag::WakeUp || mTag == Tag::NewFrameReady) {
return mCompositeNeeded;
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
return false;
const wr::FrameReadyParams& FrameReadyParams() const {
MOZ_ASSERT(mTag == Tag::NewFrameReady || mTag == Tag::WakeUp,
"Unexpected NotiferEvent tag");
return mParams;
}
FramePublishId PublishId() {
if (mTag == Tag::NewFrameReady) {
return mPublishId;
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
MOZ_ASSERT_UNREACHABLE("Unexpected NotiferEvent tag");
return FramePublishId::INVALID;
}
UniquePtr<RendererEvent> ExternalEvent() {
@@ -425,14 +431,15 @@ class RenderThread final {
MOZ_ASSERT(mRendererEvent);
return std::move(mRendererEvent);
}
MOZ_ASSERT_UNREACHABLE("unexpected to be called");
MOZ_ASSERT_UNREACHABLE("Unexpected NotiferEvent tag");
return nullptr;
}
};
explicit RenderThread(RefPtr<nsIThread> aThread);
void HandleFrameOneDocInner(wr::WindowId aWindowId, bool aRender,
void HandleFrameOneDocInner(wr::WindowId aWindowId,
const wr::FrameReadyParams& aParams,
bool aTrackedFrame,
Maybe<FramePublishId> aPublishId);
@@ -441,7 +448,7 @@ class RenderThread final {
void InitDeviceTask();
void PostResumeShaderWarmupRunnable();
void ResumeShaderWarmup();
void HandleFrameOneDoc(wr::WindowId aWindowId, bool aRender,
void HandleFrameOneDoc(wr::WindowId aWindowId, const wr::FrameReadyParams&,
bool aTrackedFrame, Maybe<FramePublishId> aPublishId);
void RunEvent(wr::WindowId aWindowId, UniquePtr<RendererEvent> aEvent,
bool aViaWebRender);
@@ -463,10 +470,10 @@ class RenderThread final {
void PostWrNotifierEvents(WrWindowId aWindowId, WindowInfo* aInfo);
void HandleWrNotifierEvents(WrWindowId aWindowId);
void WrNotifierEvent_HandleWakeUp(wr::WindowId aWindowId,
bool aCompositeNeeded);
const wr::FrameReadyParams& aParams);
void WrNotifierEvent_HandleNewFrameReady(wr::WindowId aWindowId,
bool aCompositeNeeded,
FramePublishId aPublishId);
wr::FramePublishId aPublishId,
const wr::FrameReadyParams& aParams);
void WrNotifierEvent_HandleExternalEvent(
wr::WindowId aWindowId, UniquePtr<RendererEvent> aRendererEvent);

View File

@@ -162,7 +162,7 @@ RenderedFrameId RendererOGL::UpdateAndRender(
const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<wr::ImageFormat>& aReadbackFormat,
const Maybe<Range<uint8_t>>& aReadbackBuffer, bool* aNeedsYFlip,
RendererStats* aOutStats) {
const wr::FrameReadyParams& aFrameParams, RendererStats* aOutStats) {
mozilla::widget::WidgetRenderingContext widgetContext;
#if defined(XP_MACOSX)

View File

@@ -65,7 +65,9 @@ class RendererOGL {
RenderedFrameId UpdateAndRender(const Maybe<gfx::IntSize>& aReadbackSize,
const Maybe<wr::ImageFormat>& aReadbackFormat,
const Maybe<Range<uint8_t>>& aReadbackBuffer,
bool* aNeedsYFlip, RendererStats* aOutStats);
bool* aNeedsYFlip,
const wr::FrameReadyParams& aFrameParams,
RendererStats* aOutStats);
/// This can be called on the render thread only.
void WaitForGPU();

View File

@@ -708,8 +708,13 @@ void WebRenderAPI::Readback(const TimeStamp& aStartTime, gfx::IntSize size,
void Run(RenderThread& aRenderThread, WindowId aWindowId) override {
RendererStats stats = {0};
aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime,
/* aRender */ true, Some(mSize),
wr::FrameReadyParams params = {
.present = true,
.render = true,
.scrolled = false,
};
aRenderThread.UpdateAndRender(aWindowId, VsyncId(), mStartTime, params,
Some(mSize),
wr::SurfaceFormatToImageFormat(mFormat),
Some(mBuffer), &stats, mNeedsYFlip);
layers::AutoCompleteTask complete(mTask);

View File

@@ -557,7 +557,7 @@ unsafe impl Send for CppNotifier {}
extern "C" {
fn wr_notifier_wake_up(window_id: WrWindowId, composite_needed: bool);
fn wr_notifier_new_frame_ready(window_id: WrWindowId, composite_needed: bool, publish_id: FramePublishId);
fn wr_notifier_new_frame_ready(window_id: WrWindowId, publish_id: FramePublishId, params: &FrameReadyParams);
fn wr_notifier_external_event(window_id: WrWindowId, raw_event: usize);
fn wr_schedule_render(window_id: WrWindowId, reasons: RenderReasons);
// NOTE: This moves away from pipeline_info.
@@ -579,9 +579,9 @@ impl RenderNotifier for CppNotifier {
}
}
fn new_frame_ready(&self, _: DocumentId, _scrolled: bool, composite_needed: bool, publish_id: FramePublishId) {
fn new_frame_ready(&self, _: DocumentId, publish_id: FramePublishId, params: &FrameReadyParams) {
unsafe {
wr_notifier_new_frame_ready(self.window_id, composite_needed, publish_id);
wr_notifier_new_frame_ready(self.window_id, publish_id, params);
}
}

View File

@@ -209,7 +209,7 @@ impl RenderNotifier for Notifier {
fn wake_up(&self, _composite_needed: bool) {}
fn new_frame_ready(&self, _: DocumentId, _scrolled: bool, _composite_needed: bool, _: FramePublishId) {
fn new_frame_ready(&self, _: DocumentId, _: FramePublishId, _params: &FrameReadyParams) {
self.tx.send(()).ok();
}
}

View File

@@ -38,10 +38,9 @@ impl RenderNotifier for Notifier {
fn new_frame_ready(&self,
_: DocumentId,
_scrolled: bool,
composite_needed: bool,
_: FramePublishId) {
self.wake_up(composite_needed);
_: FramePublishId,
params: &FrameReadyParams) {
self.wake_up(params.render);
}
}

View File

@@ -43,10 +43,9 @@ impl RenderNotifier for Notifier {
fn new_frame_ready(&self,
_: DocumentId,
_scrolled: bool,
composite_needed: bool,
_: FramePublishId) {
self.wake_up(composite_needed);
_: FramePublishId,
params: &FrameReadyParams) {
self.wake_up(params.render);
}
}

View File

@@ -1590,7 +1590,12 @@ impl RenderBackend {
} else if render_frame {
doc.rendered_frame_is_valid = true;
}
self.notifier.new_frame_ready(document_id, scroll, render_frame, self.frame_publish_id);
let params = api::FrameReadyParams {
present,
render: render_frame,
scrolled: scroll,
};
self.notifier.new_frame_ready(document_id, self.frame_publish_id, &params);
}
if !doc.hit_tester_is_valid {
@@ -1974,7 +1979,12 @@ impl RenderBackend {
);
self.result_tx.send(msg_publish).unwrap();
self.notifier.new_frame_ready(id, false, true, self.frame_publish_id);
let params = api::FrameReadyParams {
present: true,
render: true,
scrolled: false,
};
self.notifier.new_frame_ready(id, self.frame_publish_id, &params);
// We deserialized the state of the frame so we don't want to build
// it (but we do want to update the scene builder's state)

View File

@@ -259,6 +259,13 @@ pub struct MinimapData {
pub root_content_scroll_id: u64
}
#[repr(C)]
pub struct FrameReadyParams {
pub present: bool,
pub render: bool,
pub scrolled: bool,
}
/// A handler to integrate WebRender with the thread that contains the `Renderer`.
pub trait RenderNotifier: Send {
///
@@ -270,7 +277,7 @@ pub trait RenderNotifier: Send {
composite_needed: bool,
);
/// Notify the thread containing the `Renderer` that a new frame is ready.
fn new_frame_ready(&self, _: DocumentId, scrolled: bool, composite_needed: bool, frame_publish_id: FramePublishId);
fn new_frame_ready(&self, _: DocumentId, publish_id: FramePublishId, params: &FrameReadyParams);
/// A Gecko-specific notification mechanism to get some code executed on the
/// `Renderer`'s thread, mostly replaced by `NotificationHandler`. You should
/// probably use the latter instead.

View File

@@ -487,12 +487,11 @@ impl RenderNotifier for Notifier {
fn new_frame_ready(&self,
_: DocumentId,
_scrolled: bool,
composite_needed: bool,
_: FramePublishId) {
_: FramePublishId,
params: &FrameReadyParams) {
// TODO(gw): Refactor wrench so that it can take advantage of cases
// where no composite is required when appropriate.
self.wake_up(composite_needed);
self.wake_up(params.render);
}
}

View File

@@ -112,11 +112,8 @@ impl RenderNotifier for Notifier {
self.update(false);
}
fn new_frame_ready(&self, _: DocumentId,
scrolled: bool,
_composite_needed: bool,
_: FramePublishId) {
self.update(!scrolled);
fn new_frame_ready(&self, _: DocumentId, _: FramePublishId, params: &FrameReadyParams) {
self.update(!params.scrolled);
}
}