1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
// Copyright 2021 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/base/x/x11_xrandr_interval_only_vsync_provider.h"
#include "base/functional/bind.h"
#include "base/no_destructor.h"
#include "base/task/single_thread_task_runner.h"
#include "ui/base/x/x11_display_util.h"
#include "ui/gfx/x/connection.h"
#include "ui/gfx/x/event.h"
#include "ui/gfx/x/future.h"
#include "ui/gfx/x/randr.h"
namespace ui {
namespace {
bool IsXrandrAvailable() {
constexpr std::pair<uint32_t, uint32_t> kMinXrandrVersion{1, 3};
return x11::Connection::Get()->randr_version() >= kMinXrandrVersion;
}
class XRandrHelper : public x11::EventObserver {
public:
XRandrHelper() {
DCHECK(IsXrandrAvailable());
auto* connection = x11::Connection::Get();
auto root_window = connection->default_screen().root;
auto& randr = connection->randr();
auto randr_event_mask = x11::RandR::NotifyMask::OutputChange;
randr.SelectInput({root_window, randr_event_mask});
connection->AddEventObserver(this);
}
~XRandrHelper() override {
auto* connection = x11::Connection::Get();
connection->RemoveEventObserver(this);
}
// x11::EventObserver:
void OnEvent(const x11::Event& xevent) override {
if (xevent.As<x11::RandR::NotifyEvent>()) {
interval_ = {};
}
}
static base::TimeDelta GetInterval() {
if (IsXrandrAvailable()) {
static base::NoDestructor<XRandrHelper> helper;
return helper->GetIntervalInternal();
}
constexpr auto kDefaultInterval = base::Seconds(1) / 60;
return kDefaultInterval;
}
private:
base::TimeDelta GetIntervalInternal() {
if (interval_.is_zero()) {
interval_ = GetPrimaryDisplayRefreshIntervalFromXrandr();
}
return interval_;
}
base::TimeDelta interval_;
};
} // namespace
XrandrIntervalOnlyVSyncProvider::XrandrIntervalOnlyVSyncProvider() = default;
XrandrIntervalOnlyVSyncProvider::~XrandrIntervalOnlyVSyncProvider() = default;
void XrandrIntervalOnlyVSyncProvider::GetVSyncParameters(
UpdateVSyncCallback callback) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), base::TimeTicks(),
XRandrHelper::GetInterval()));
}
bool XrandrIntervalOnlyVSyncProvider::GetVSyncParametersIfAvailable(
base::TimeTicks* timebase,
base::TimeDelta* interval) {
*interval = XRandrHelper::GetInterval();
return true;
}
bool XrandrIntervalOnlyVSyncProvider::SupportGetVSyncParametersIfAvailable()
const {
return true;
}
bool XrandrIntervalOnlyVSyncProvider::IsHWClock() const {
return false;
}
} // namespace ui
|