Commit 19cdf8b2 authored by Eliot Courtney's avatar Eliot Courtney Committed by Commit Bot

[ozone/wayland] Save a task runner for each calling thread.

WaylandBufferManagerGpu assumes that it will always be called from the
main GPU thread and only saves the task runner for the thread of the
first caller. However, WaylandCanvasSurface runs on VizCompositorThread,
so it's necessary to save multiple task runners.

Bug: 1103101
Test: Launching chrome no longer DCHECKs per the bug
Change-Id: I8277ca17a1bbbe572c6471fb86df42046efb3be7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2306128Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Commit-Queue: Eliot Courtney <edcourtney@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790637}
parent ce2d1dc1
......@@ -64,16 +64,37 @@ void WaylandBufferManagerGpu::OnPresentation(
void WaylandBufferManagerGpu::RegisterSurface(gfx::AcceleratedWidget widget,
WaylandSurfaceGpu* surface) {
if (!io_thread_runner_) {
LOG(ERROR) << "WaylandBufferManagerGpu is not initialized. Can't register "
"a surface.";
return;
}
io_thread_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&WaylandBufferManagerGpu::SaveTaskRunnerForWidgetOnIOThread,
base::Unretained(this), widget, base::ThreadTaskRunnerHandle::Get()));
base::AutoLock scoped_lock(lock_);
widget_to_surface_map_.emplace(widget, surface);
commit_thread_runners_.insert(
std::make_pair(widget, base::ThreadTaskRunnerHandle::Get()));
}
void WaylandBufferManagerGpu::UnregisterSurface(gfx::AcceleratedWidget widget) {
if (!io_thread_runner_) {
LOG(ERROR) << "WaylandBufferManagerGpu is not initialized. Can't register "
"a surface.";
return;
}
io_thread_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&WaylandBufferManagerGpu::ForgetTaskRunnerForWidgetOnIOThread,
base::Unretained(this), widget));
base::AutoLock scoped_lock(lock_);
widget_to_surface_map_.erase(widget);
commit_thread_runners_.erase(widget);
}
WaylandSurfaceGpu* WaylandBufferManagerGpu::GetSurface(
......@@ -232,6 +253,21 @@ void WaylandBufferManagerGpu::BindHostInterface(
remote_host_->SetWaylandBufferManagerGpu(std::move(client_remote));
}
void WaylandBufferManagerGpu::SaveTaskRunnerForWidgetOnIOThread(
gfx::AcceleratedWidget widget,
scoped_refptr<base::SingleThreadTaskRunner> origin_runner) {
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
DCHECK(io_thread_runner_->BelongsToCurrentThread());
commit_thread_runners_.emplace(widget, origin_runner);
}
void WaylandBufferManagerGpu::ForgetTaskRunnerForWidgetOnIOThread(
gfx::AcceleratedWidget widget) {
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
DCHECK(io_thread_runner_->BelongsToCurrentThread());
commit_thread_runners_.erase(widget);
}
void WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread(
gfx::AcceleratedWidget widget,
uint32_t buffer_id,
......@@ -239,15 +275,8 @@ void WaylandBufferManagerGpu::SubmitSwapResultOnOriginThread(
DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
auto* surface = GetSurface(widget);
// The surface might be destroyed by the time the swap result is provided.
if (surface) {
#if DCHECK_IS_ON()
base::AutoLock scoped_lock(lock_);
DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
DCHECK(
commit_thread_runners_.find(widget)->second->BelongsToCurrentThread());
#endif
if (surface)
surface->OnSubmission(buffer_id, swap_result);
}
}
void WaylandBufferManagerGpu::SubmitPresentationOnOriginThread(
......@@ -258,15 +287,8 @@ void WaylandBufferManagerGpu::SubmitPresentationOnOriginThread(
auto* surface = GetSurface(widget);
// The surface might be destroyed by the time the presentation feedback is
// provided.
if (surface) {
#if DCHECK_IS_ON()
base::AutoLock scoped_lock(lock_);
DCHECK_EQ(commit_thread_runners_.count(widget), 1u);
DCHECK(
commit_thread_runners_.find(widget)->second->BelongsToCurrentThread());
#endif
if (surface)
surface->OnPresentation(buffer_id, feedback);
}
}
} // namespace ui
......@@ -148,6 +148,11 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
void BindHostInterface(
mojo::PendingRemote<ozone::mojom::WaylandBufferManagerHost> remote_host);
void SaveTaskRunnerForWidgetOnIOThread(
gfx::AcceleratedWidget widget,
scoped_refptr<base::SingleThreadTaskRunner> origin_runner);
void ForgetTaskRunnerForWidgetOnIOThread(gfx::AcceleratedWidget widget);
// Provides the WaylandSurfaceGpu, which backs the |widget|, with swap and
// presentation results.
void SubmitSwapResultOnOriginThread(gfx::AcceleratedWidget widget,
......@@ -181,16 +186,17 @@ class WaylandBufferManagerGpu : public ozone::mojom::WaylandBufferManagerGpu {
base::flat_map<gfx::BufferFormat, std::vector<uint64_t>>
supported_buffer_formats_with_modifiers_;
// This task runner can be used to pass messages back to the same thread,
// These task runners can be used to pass messages back to the same thread,
// where the commit buffer request came from. For example, swap requests can
// come from the GpuMainThread, but rerouted are to the IOChildThread and then
// come from the GpuMainThread, but are rerouted to the IOChildThread and then
// mojo calls happen. However, when the manager receives mojo calls, it has to
// reroute calls back to the same thread where the calls came from to ensure
// correct sequence. Note that not all calls come from the GpuMainThread, e.g.
// WaylandCanvasSurface calls from the VizCompositorThread.
// This map must only be accessed from the IO thread.
base::small_map<std::map<gfx::AcceleratedWidget,
scoped_refptr<base::SingleThreadTaskRunner>>>
commit_thread_runners_; // Guarded by |lock_|.
commit_thread_runners_;
// A task runner, which is initialized in a multi-process mode. It is used to
// ensure all the methods of this class are run on IOChildThread. This is
......
......@@ -508,6 +508,7 @@ class WaylandBufferManagerHost::Surface {
}
void MaybeProcessPendingBuffer() {
DCHECK_LE(pending_buffers_.size(), 6u);
// There is nothing to process if there is no pending buffer or the window
// has been destroyed.
if (pending_buffers_.empty() || !wayland_surface_)
......
......@@ -50,7 +50,6 @@ class MockSurfaceGpu : public WaylandSurfaceGpu {
MockSurfaceGpu(WaylandBufferManagerGpu* buffer_manager,
gfx::AcceleratedWidget widget)
: buffer_manager_(buffer_manager), widget_(widget) {
LOG(ERROR) << "MOCKSURFACEGPU: " << widget_;
buffer_manager_->RegisterSurface(widget_, this);
}
~MockSurfaceGpu() { buffer_manager_->UnregisterSurface(widget_); }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment