Commit 704bb824 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

Use WindowResizeHelperMac message pump in CATransactionCoordinator

Running a full nested NSRunLoop appears to cause problems wherein
CATransactions are created from within a CATransaction's commit
handlers.

Bug: 853438
Change-Id: I37e9d3f92025c8b45201e23109a87e02afd6085c
Reviewed-on: https://chromium-review.googlesource.com/1100239
Commit-Queue: ccameron <ccameron@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Reviewed-by: default avatarSidney San Martín <sdy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567926}
parent c2ab739e
......@@ -33,6 +33,10 @@
#include "services/service_manager/runner/common/client_util.h"
#include "ui/base/ui_base_features.h"
#if defined(OS_MACOSX)
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
namespace content {
#if defined(OS_ANDROID)
......@@ -108,7 +112,13 @@ BrowserGpuChannelHostFactory::EstablishRequest::EstablishRequest(
gpu_client_id_(gpu_client_id),
gpu_client_tracing_id_(gpu_client_tracing_id),
finished_(false),
main_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
#if defined(OS_MACOSX)
main_task_runner_(ui::WindowResizeHelperMac::Get()->task_runner())
#else
main_task_runner_(base::ThreadTaskRunnerHandle::Get())
#endif
{
}
void BrowserGpuChannelHostFactory::EstablishRequest::RestartTimeout() {
BrowserGpuChannelHostFactory* factory =
......
......@@ -9,14 +9,15 @@
#include "content/public/browser/browser_thread.h"
#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
namespace content {
CATransactionGPUCoordinator::CATransactionGPUCoordinator(GpuProcessHost* host)
: host_(host) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&ui::CATransactionCoordinator::AddPostCommitObserver,
base::Unretained(&ui::CATransactionCoordinator::Get()),
base::RetainedRef(this)));
......@@ -28,8 +29,8 @@ CATransactionGPUCoordinator::~CATransactionGPUCoordinator() {
void CATransactionGPUCoordinator::HostWillBeDestroyed() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&ui::CATransactionCoordinator::RemovePostCommitObserver,
base::Unretained(&ui::CATransactionCoordinator::Get()),
base::RetainedRef(this)));
......@@ -78,8 +79,8 @@ void CATransactionGPUCoordinator::OnEnterPostCommitOnIO() {
void CATransactionGPUCoordinator::OnCommitCompletedOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
ui::WindowResizeHelperMac::Get()->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&CATransactionGPUCoordinator::OnCommitCompletedOnUI,
this));
}
......
......@@ -75,6 +75,8 @@ class ACCELERATED_WIDGET_MAC_EXPORT CATransactionCoordinator {
API_AVAILABLE(macos(10.11))
void SynchronizeImpl();
void PreCommitHandler();
void PostCommitHandler();
bool active_ = false;
base::ObserverList<PreCommitObserver> pre_commit_observers_;
......
......@@ -5,7 +5,9 @@
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "base/no_destructor.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#import <AppKit/AppKit.h>
#import <CoreFoundation/CoreFoundation.h>
......@@ -50,46 +52,64 @@ void CATransactionCoordinator::SynchronizeImpl() {
observer.OnActivateForTransaction();
[CATransaction addCommitHandler:^{
TRACE_EVENT0("ui", "CATransactionCoordinator: pre-commit handler");
NSDate* start_date = [NSDate date];
for (;;) {
base::TimeDelta timeout;
for (auto& observer : pre_commit_observers_) {
if (observer.ShouldWaitInPreCommit())
timeout = std::max(timeout, observer.PreCommitTimeout());
}
NSDate* deadline =
[start_date dateByAddingTimeInterval:timeout.InSecondsF()];
if ([deadline isLessThanOrEqualTo:[NSDate date]])
break;
[NSRunLoop.currentRunLoop runMode:kRunLoopMode beforeDate:deadline];
}
PreCommitHandler();
}
forPhase:kCATransactionPhasePreCommit];
[CATransaction addCommitHandler:^{
TRACE_EVENT0("ui", "CATransactionCoordinator: post-commit handler");
for (auto& observer : post_commit_observers_)
observer.OnEnterPostCommit();
NSDate* deadline =
[NSDate dateWithTimeIntervalSinceNow:kPostCommitTimeout.InSecondsF()];
for (;;) {
if (!std::any_of(
post_commit_observers_.begin(), post_commit_observers_.end(),
std::mem_fn(&PostCommitObserver::ShouldWaitInPostCommit)))
break;
if ([deadline isLessThanOrEqualTo:[NSDate date]])
break;
[NSRunLoop.currentRunLoop runMode:kRunLoopMode beforeDate:deadline];
}
active_ = false;
PostCommitHandler();
}
forPhase:kCATransactionPhasePostCommit];
}
void CATransactionCoordinator::PreCommitHandler() {
TRACE_EVENT0("ui", "CATransactionCoordinator: pre-commit handler");
auto* clock = base::DefaultTickClock::GetInstance();
const base::TimeTicks start_time = clock->NowTicks();
while (true) {
bool continue_waiting = false;
base::TimeTicks deadline = start_time;
for (auto& observer : pre_commit_observers_) {
if (observer.ShouldWaitInPreCommit()) {
continue_waiting = true;
deadline = std::max(deadline, start_time + observer.PreCommitTimeout());
}
}
if (!continue_waiting)
break; // success
base::TimeDelta time_left = deadline - clock->NowTicks();
if (time_left <= base::TimeDelta::FromSeconds(0))
break; // timeout
ui::WindowResizeHelperMac::Get()->WaitForSingleTaskToRun(time_left);
}
}
void CATransactionCoordinator::PostCommitHandler() {
TRACE_EVENT0("ui", "CATransactionCoordinator: post-commit handler");
for (auto& observer : post_commit_observers_)
observer.OnEnterPostCommit();
auto* clock = base::DefaultTickClock::GetInstance();
const base::TimeTicks deadline = clock->NowTicks() + kPostCommitTimeout;
while (true) {
bool continue_waiting = std::any_of(
post_commit_observers_.begin(), post_commit_observers_.end(),
std::mem_fn(&PostCommitObserver::ShouldWaitInPostCommit));
if (!continue_waiting)
break; // success
base::TimeDelta time_left = deadline - clock->NowTicks();
if (time_left <= base::TimeDelta::FromSeconds(0))
break; // timeout
ui::WindowResizeHelperMac::Get()->WaitForSingleTaskToRun(time_left);
}
active_ = false;
}
CATransactionCoordinator::CATransactionCoordinator() = default;
CATransactionCoordinator::~CATransactionCoordinator() = default;
......
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