// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/compositor/recyclable_compositor_mac.h"
#include "base/functional/bind.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_runner.h"
#include "components/viz/common/features.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/display/types/display_constants.h"
namespace ui {
namespace {
// Returns a task runner for creating a ui::Compositor. This allows compositor
// tasks to be funneled through ui::WindowResizeHelper's task runner to allow
// resize operations to coordinate with frames provided by the GPU process.
scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() {
// If the WindowResizeHelper's pumpable task runner is set, it means the GPU
// process is directing messages there, and the compositor can synchronize
// with it. Otherwise, just use the UI thread.
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
ui::WindowResizeHelperMac::Get()->task_runner();
return task_runner ? task_runner
: base::SingleThreadTaskRunner::GetCurrentDefault();
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
// RecyclableCompositorMac
RecyclableCompositorMac::RecyclableCompositorMac(
ui::ContextFactory* context_factory)
: accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(context_factory->AllocateFrameSinkId(),
context_factory,
GetCompositorTaskRunner(),
ui::IsPixelCanvasRecordingEnabled()) {
compositor_.SetAcceleratedWidget(
accelerated_widget_mac_->accelerated_widget());
Suspend();
compositor_.AddObserver(this);
}
RecyclableCompositorMac::~RecyclableCompositorMac() {
compositor_.RemoveObserver(this);
}
void RecyclableCompositorMac::Suspend() {
// Requests a compositor lock without a timeout.
compositor_suspended_lock_ =
compositor_.GetCompositorLock(nullptr, base::TimeDelta());
}
void RecyclableCompositorMac::Unsuspend() {
compositor_suspended_lock_ = nullptr;
}
void RecyclableCompositorMac::UpdateSurface(
const gfx::Size& size_pixels,
float scale_factor,
const gfx::DisplayColorSpaces& display_color_spaces,
int64_t display_id) {
if (size_pixels != size_pixels_ || scale_factor != scale_factor_) {
size_pixels_ = size_pixels;
scale_factor_ = scale_factor;
local_surface_id_allocator_.GenerateId();
viz::LocalSurfaceId local_surface_id =
local_surface_id_allocator_.GetCurrentLocalSurfaceId();
compositor()->SetScaleAndSize(scale_factor_, size_pixels_,
local_surface_id);
}
compositor()->SetDisplayColorSpaces(display_color_spaces);
compositor()->SetVSyncDisplayID(display_id);
}
void RecyclableCompositorMac::InvalidateSurface() {
size_pixels_ = gfx::Size();
scale_factor_ = 1.f;
local_surface_id_allocator_.Invalidate();
compositor()->SetScaleAndSize(
scale_factor_, size_pixels_,
local_surface_id_allocator_.GetCurrentLocalSurfaceId());
compositor()->SetDisplayColorSpaces(gfx::DisplayColorSpaces());
compositor()->SetVSyncDisplayID(display::kInvalidDisplayId);
}
void RecyclableCompositorMac::OnCompositingDidCommit(
ui::Compositor* compositor_that_did_commit) {
DCHECK_EQ(compositor_that_did_commit, compositor());
accelerated_widget_mac_->SetSuspended(false);
}
} // namespace ui