Commit 92eb1015 authored by Malay Keshav's avatar Malay Keshav Committed by Commit Bot

Ash: Add UMA to measure primary display's effective resolution

Adds an UMA metric that tracks the effective resolution of the primary
display. To ensure the metric being measured is one that the user is to
spends most time on, the signal is sent at every fixed interval of
30 minutes.

Effective resolution takes into account the display zoom, device scale
factor, and the display rotation.

Bug: 1126489
Test: Tested manually on atlas and krane
Change-Id: Id0f92867c6927f06f0c5c2288198f5bff3a5b8b1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2412837Reviewed-by: default avatarJesse Doherty <jwd@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Commit-Queue: Malay Keshav <malaykeshav@chromium.org>
Auto-Submit: Malay Keshav <malaykeshav@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814037}
parent db8f4f0a
......@@ -21,12 +21,14 @@
#include "ash/public/cpp/ash_features.h"
#include "ash/root_window_controller.h"
#include "ash/root_window_settings.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
......@@ -67,6 +69,12 @@ int64_t primary_display_id = -1;
// The default memory limit: 512mb.
const char kUICompositorDefaultMemoryLimitMB[] = "512";
// An UMA signal for the current effective resolution is sent at this rate. This
// keeps track of the effective resolution most used on internal display by the
// user.
constexpr base::TimeDelta kEffectiveResolutionRepeatingDelay =
base::TimeDelta::FromMinutes(30);
display::DisplayManager* GetDisplayManager() {
return Shell::Get()->display_manager();
}
......@@ -98,6 +106,47 @@ aura::Window* GetWindow(AshWindowTreeHost* ash_host) {
return ash_host->AsWindowTreeHost()->window();
}
// Returns the index to the enum - |EffectiveResolution|. The enum value
// represents the resolution that exactly matches the primary display's
// effective resolution.
int GetEffectiveResolutionUMAIndex(const display::Display& display) {
const gfx::Size effective_size = display.size();
// The UMA enum index for portrait mode has 1 subtracted from itself. This
// differentiates it from the landscape mode.
return effective_size.width() > effective_size.height()
? effective_size.width() * effective_size.height()
: effective_size.width() * effective_size.height() - 1;
}
void RepeatingEffectiveResolutionUMA(base::RepeatingTimer* timer,
bool is_first_run) {
display::Display internal_display;
const auto* session_controller = Shell::Get()->session_controller();
// Record the UMA only when this is an active user session and the
// internal display is present.
if (display::Display::HasInternalDisplay() &&
display::Screen::GetScreen()->GetDisplayWithDisplayId(
display::Display::InternalDisplayId(), &internal_display) &&
session_controller->IsActiveUserSessionStarted() &&
session_controller->GetSessionState() ==
session_manager::SessionState::ACTIVE) {
base::UmaHistogramSparse(
"Ash.Display.InternalDisplay.ActiveEffectiveResolution",
GetEffectiveResolutionUMAIndex(internal_display));
}
// The first run of the repeating timer is half the actual delay. Reset the
// timer after the first run with the correct delay.
if (is_first_run && timer) {
timer->Start(
FROM_HERE, kEffectiveResolutionRepeatingDelay,
base::BindRepeating(&RepeatingEffectiveResolutionUMA,
nullptr /*timer=*/, false /*is_first_run=*/));
}
}
} // namespace
// A utility class to store/restore focused/active window
......@@ -191,12 +240,23 @@ void WindowTreeHostManager::Start() {
->content_protection_manager()
->AddObserver(this);
Shell::Get()->display_manager()->set_delegate(this);
// Start a repeating timer to send UMA at fixed intervals. The first run is at
// half the delay time.
effective_resolution_UMA_timer_ = std::make_unique<base::RepeatingTimer>();
effective_resolution_UMA_timer_->Start(
FROM_HERE, kEffectiveResolutionRepeatingDelay / 2,
base::BindRepeating(&RepeatingEffectiveResolutionUMA,
effective_resolution_UMA_timer_.get(),
true /*is_first_run=*/));
}
void WindowTreeHostManager::Shutdown() {
for (auto& observer : observers_)
observer.OnWindowTreeHostManagerShutdown();
effective_resolution_UMA_timer_->Reset();
// Unset the display manager's delegate here because
// DisplayManager outlives WindowTreeHostManager.
Shell::Get()->display_manager()->set_delegate(nullptr);
......
......@@ -18,6 +18,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host_observer.h"
#include "ui/base/ime/input_method.h"
......@@ -205,6 +206,10 @@ class ASH_EXPORT WindowTreeHostManager
// should be moved after a display configuration change.
int64_t cursor_display_id_for_restore_;
// A repeating timer to trigger sending UMA metrics for primary display's
// effective resolution at fixed intervals.
std::unique_ptr<base::RepeatingTimer> effective_resolution_UMA_timer_;
base::WeakPtrFactory<WindowTreeHostManager> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManager);
......
This diff is collapsed.
......@@ -471,6 +471,17 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary>
</histogram>
<histogram name="Ash.Display.InternalDisplay.ActiveEffectiveResolution"
enum="EffectiveResolution" expires_after="2021-09-01">
<owner>malaykeshav@chromium.org</owner>
<owner>oshima@chromium.org</owner>
<summary>
The effective resolution of the internal display after device scale factor
and display zoom level has been applied. This is the exact value matching
the display's effective resolution. This is emitted at regular intervals.
</summary>
</histogram>
<histogram name="Ash.Display.PrimaryDisplayZoomAtStartup" units="%"
expires_after="2020-09-06">
<owner>jamescook@chromium.org</owner>
......
......@@ -431,11 +431,12 @@ float DisplayChangeObserver::FindDeviceScaleFactor(
// Nocturne has special scale factor 3000/1332=2.252.. for the panel 3kx2k.
constexpr gfx::Size k225DisplaySizeHackNocturne(3000, 2000);
// Keep the Chell's scale factor 2.252 until we make decision.
constexpr gfx::Size k225DisplaySizeHackChell(3200, 1800);
constexpr gfx::Size k2DisplaySizeHackChell(3200, 1800);
if (size_in_pixels == k225DisplaySizeHackNocturne ||
size_in_pixels == k225DisplaySizeHackChell) {
if (size_in_pixels == k225DisplaySizeHackNocturne) {
return kDsf_2_252;
} else if (size_in_pixels == k2DisplaySizeHackChell) {
return 2.f;
} else {
for (size_t i = 0; i < base::size(kThresholdTableForInternal); ++i) {
if (dpi >= kThresholdTableForInternal[i].dpi)
......
......@@ -4,6 +4,7 @@
#include "ui/display/manager/display_change_observer.h"
#include <cmath>
#include <string>
#include "base/strings/stringprintf.h"
......@@ -17,9 +18,12 @@
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
#include "ui/display/screen.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_mode.h"
#include "ui/events/devices/device_data_manager.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/range/range_f.h"
......@@ -229,76 +233,6 @@ TEST_P(DisplayChangeObserverTest, FindDeviceScaleFactor) {
EXPECT_EQ(kDsf_2_666,
DisplayChangeObserver::FindDeviceScaleFactor(310, gfx::Size()));
// Valid Displays
constexpr gfx::Size kWXGA_768{1366, 768};
constexpr gfx::Size kWXGA_800{1280, 800};
constexpr gfx::Size kHD_PLUS{1600, 900};
constexpr gfx::Size kFHD{1920, 1080};
constexpr gfx::Size kWUXGA{1920, 1200};
// Dru
constexpr gfx::Size kQXGA_P{1536, 2048};
constexpr gfx::Size kQHD{2560, 1440};
// Chell
constexpr gfx::Size kQHD_PLUS{3200, 1800};
constexpr gfx::Size kUHD{3840, 2160};
// Chromebook special panels
constexpr gfx::Size kLux{2160, 1440};
constexpr gfx::Size kAkaliQHD{2256, 1504};
constexpr gfx::Size kLink{2560, 1700};
constexpr gfx::Size kEve{2400, 1600};
constexpr gfx::Size kNocturne{3000, 2000};
enum SizeErrorCheckType {
kExact, // Exact match.
kEpsilon, // Matches within epsilon.
kSkip, // Skip testing the error.
};
constexpr struct Data {
const float diagonal_size;
const gfx::Size resolution;
const float expected_dsf;
const gfx::Size expected_dp_size;
const bool bad_range;
const SizeErrorCheckType screenshot_size_error;
} display_configs[] = {
// clang-format off
// inch, resolution, DSF, size in DP, Bad range, size error
{10.1f, kWXGA_800, 1.f, kWXGA_800, false, kExact},
{12.1f, kWXGA_800, 1.0f, kWXGA_800, true, kExact},
{11.6f, kWXGA_768, 1.f, kWXGA_768, false, kExact},
{13.3f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{14.f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{15.6f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{9.7f, kQXGA_P, 2.0f, {768, 1024}, false, kExact},
{11.6f, kFHD, 1.6f, {1200, 675}, false, kExact},
{13.0f, kFHD, 1.25f, {1536, 864}, true, kExact},
{13.3f, kFHD, 1.25f, {1536, 864}, true, kExact},
{14.f, kFHD, 1.25f, {1536, 864}, false, kExact},
{10.1f, kWUXGA, kDsf_1_777, {1080, 675}, false, kExact},
{12.2f, kWUXGA, 1.6f, {1200, 750}, false, kExact},
{15.6f, kWUXGA, 1.f, kWUXGA, false, kExact},
{12.3f, kQHD, 2.f, {1280, 720}, false, kExact},
// Non standard panels
{11.0f, kLux, 2.f, {1080, 720}, false, kExact},
{12.02f, kLux, 1.6f, {1350, 900}, true, kExact},
{13.3f, kQHD_PLUS, kDsf_2_252, {1421, 800}, false, kSkip},
{13.3f, kAkaliQHD, 1.6f, {1410, 940}, false, kExact},
{12.3f, kEve, 2.0f, {1200, 800}, false, kExact},
{12.85f, kLink, 2.0f, {1280, 850}, false, kExact},
{12.3f, kNocturne, kDsf_2_252, {1332, 888}, false, kEpsilon},
{13.1f, kUHD, kDsf_2_666, {1440, 810}, false, kExact},
{15.6f, kUHD, 2.4f, {1600, 900}, false, kEpsilon},
// Chromebase
{19.5, kHD_PLUS, 1.f, kHD_PLUS, true, kExact},
{21.5f, kFHD, 1.f, kFHD, true, kExact},
{23.8f, kFHD, 1.f, kFHD, true, kExact},
// clang-format on
};
for (auto& entry : display_configs) {
SCOPED_TRACE(base::StringPrintf(
"%dx%d, diag=%1.3f inch, expected=%1.10f", entry.resolution.width(),
......@@ -547,4 +481,67 @@ INSTANTIATE_TEST_SUITE_P(All,
DisplayChangeObserverTest,
::testing::Values(false, true));
#if defined(OS_CHROMEOS)
using DisplayResolutionTest = testing::Test;
TEST_F(DisplayResolutionTest, CheckEffectiveResoutionUMAIndex) {
std::map<int, gfx::Size> effective_resolutions;
for (const auto& display_config : display_configs) {
gfx::Size size = display_config.resolution;
if (size.width() < size.height())
size = gfx::Size(size.height(), size.width());
const float dsf = display_config.expected_dsf;
std::array<float, kNumOfZoomFactors> zoom_levels;
if (dsf == 1.f) {
for (const ZoomListBucket& zoom_list_bucket : kZoomListBuckets) {
if (size.width() >= zoom_list_bucket.first)
zoom_levels = zoom_list_bucket.second;
}
} else {
for (const ZoomListBucketDsf& zoom_list_bucket : kZoomListBucketsForDsf) {
if (cc::MathUtil::IsWithinEpsilon(dsf, zoom_list_bucket.first))
zoom_levels = zoom_list_bucket.second;
}
}
for (float zoom_level : zoom_levels) {
float effective_scale = 1.f / (zoom_level * dsf);
gfx::SizeF effective_resolution_f(size);
effective_resolution_f.Scale(effective_scale);
gfx::Size effective_resolution =
gfx::ToEnclosedRectIgnoringError(gfx::RectF(effective_resolution_f),
0.01f)
.size();
gfx::Size portrait_effective_resolution = gfx::Size(
effective_resolution.height(), effective_resolution.width());
const int landscape_key =
effective_resolution.width() * effective_resolution.height();
const int portrait_key = landscape_key - 1;
auto it = effective_resolutions.find(landscape_key);
if (it != effective_resolutions.end())
EXPECT_EQ(it->second, effective_resolution);
else
effective_resolutions[landscape_key] = effective_resolution;
it = effective_resolutions.find(portrait_key);
if (it != effective_resolutions.end())
EXPECT_EQ(it->second, portrait_effective_resolution);
else
effective_resolutions[portrait_key] = portrait_effective_resolution;
}
}
// With the current set of display configs and zoom levels, there are only 288
// possible effective resolutions for internal displays in chromebooks. Update
// this value when adding a new display config.
EXPECT_EQ(effective_resolutions.size(), 288ul);
}
#endif
} // namespace display
......@@ -17,53 +17,6 @@
#include "ui/display/types/display_snapshot.h"
namespace display {
namespace {
// The total number of display zoom factors to enumerate.
constexpr int kNumOfZoomFactors = 9;
// A pair representing the list of zoom values for a given minimum display
// resolution width.
using ZoomListBucket = std::pair<int, std::array<float, kNumOfZoomFactors>>;
// A pair representing the list of zoom values for a given minimum default dsf.
using ZoomListBucketDsf =
std::pair<float, std::array<float, kNumOfZoomFactors>>;
// For displays with a device scale factor of unity, we use a static list of
// initialized zoom values. For a given resolution width of a display, we can
// find its associated list of zoom values by simply finding the last bucket
// with a width less than the given resolution width.
// Ex. A resolution width of 1024, we will use the bucket with the width of 960.
constexpr std::array<ZoomListBucket, 8> kZoomListBuckets{{
{0, {0.60f, 0.65f, 0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f}},
{720, {0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f, 1.05f, 1.10f}},
{800, {0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f, 1.05f, 1.10f, 1.15f}},
{960, {0.90f, 0.95f, 1.f, 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f}},
{1280, {0.90f, 1.f, 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f, 1.50f}},
{1920, {1.f, 1.10f, 1.15f, 1.20f, 1.30f, 1.40f, 1.50f, 1.75f, 2.00f}},
{3840, {1.f, 1.10f, 1.20f, 1.40f, 1.60f, 1.80f, 2.00f, 2.20f, 2.40f}},
{5120, {1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f, 3.00f}},
}};
// Displays with a default device scale factor have a static list of initialized
// zoom values that includes a zoom level to go to the native resolution of the
// display. Ensure that the list of DSFs are in sync with the list of default
// device scale factors in display_change_observer.cc.
constexpr std::array<ZoomListBucketDsf, 7> kZoomListBucketsForDsf{{
{1.25f, {0.7f, 1.f / 1.25f, 0.85f, 0.9f, 0.95f, 1.f, 1.1f, 1.2f, 1.3f}},
{1.6f, {1.f / 1.6f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.f, 1.15f, 1.3f}},
{kDsf_1_777,
{1.f / kDsf_1_777, 0.65f, 0.75f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f}},
{2.f, {1.f / 2.f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.25f, 1.5f}},
{kDsf_2_252,
{1.f / kDsf_2_252, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.15f, 1.3f, 1.5f}},
{2.4f, {1.f / 2.4f, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}},
{kDsf_2_666,
{1.f / kDsf_2_666, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}},
}};
} // namespace
#if defined(OS_CHROMEOS)
std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) {
......
......@@ -6,6 +6,9 @@
#define UI_DISPLAY_TYPES_DISPLAY_CONSTANTS_H_
#include <stdint.h>
#include <array>
#include "ui/gfx/geometry/size_conversions.h"
namespace display {
......@@ -97,6 +100,121 @@ constexpr char kDsfStr_1_777[] = "1.77777779102325439453125";
constexpr char kDsfStr_2_252[] = "2.2522523403167724609375";
constexpr char kDsfStr_2_666[] = "2.6666667461395263671875";
// The total number of display zoom factors to enumerate.
constexpr int kNumOfZoomFactors = 9;
// A pair representing the list of zoom values for a given minimum display
// resolution width.
using ZoomListBucket = std::pair<int, std::array<float, kNumOfZoomFactors>>;
// A pair representing the list of zoom values for a given minimum default dsf.
using ZoomListBucketDsf =
std::pair<float, std::array<float, kNumOfZoomFactors>>;
// For displays with a device scale factor of unity, we use a static list of
// initialized zoom values. For a given resolution width of a display, we can
// find its associated list of zoom values by simply finding the last bucket
// with a width less than the given resolution width.
// Ex. A resolution width of 1024, we will use the bucket with the width of 960.
constexpr std::array<ZoomListBucket, 8> kZoomListBuckets{{
{0, {0.60f, 0.65f, 0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f}},
{720, {0.70f, 0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f, 1.05f, 1.10f}},
{800, {0.75f, 0.80f, 0.85f, 0.90f, 0.95f, 1.f, 1.05f, 1.10f, 1.15f}},
{960, {0.90f, 0.95f, 1.f, 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f}},
{1280, {0.90f, 1.f, 1.05f, 1.10f, 1.15f, 1.20f, 1.25f, 1.30f, 1.50f}},
{1920, {1.f, 1.10f, 1.15f, 1.20f, 1.30f, 1.40f, 1.50f, 1.75f, 2.00f}},
{3840, {1.f, 1.10f, 1.20f, 1.40f, 1.60f, 1.80f, 2.00f, 2.20f, 2.40f}},
{5120, {1.f, 1.25f, 1.50f, 1.75f, 2.00f, 2.25f, 2.50f, 2.75f, 3.00f}},
}};
// Displays with a default device scale factor have a static list of initialized
// zoom values that includes a zoom level to go to the native resolution of the
// display. Ensure that the list of DSFs are in sync with the list of default
// device scale factors in display_change_observer.cc.
constexpr std::array<ZoomListBucketDsf, 7> kZoomListBucketsForDsf{{
{1.25f, {0.7f, 1.f / 1.25f, 0.85f, 0.9f, 0.95f, 1.f, 1.1f, 1.2f, 1.3f}},
{1.6f, {1.f / 1.6f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.f, 1.15f, 1.3f}},
{kDsf_1_777,
{1.f / kDsf_1_777, 0.65f, 0.75f, 0.8f, 0.9f, 1.f, 1.1f, 1.2f, 1.3f}},
{2.f, {1.f / 2.f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.25f, 1.5f}},
{kDsf_2_252,
{1.f / kDsf_2_252, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.15f, 1.3f, 1.5f}},
{2.4f, {1.f / 2.4f, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}},
{kDsf_2_666,
{1.f / kDsf_2_666, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}},
}};
// Valid Displays
constexpr gfx::Size kWXGA_768{1366, 768};
constexpr gfx::Size kWXGA_800{1280, 800};
constexpr gfx::Size kHD_PLUS{1600, 900};
constexpr gfx::Size kFHD{1920, 1080};
constexpr gfx::Size kWUXGA{1920, 1200};
// Dru
constexpr gfx::Size kQXGA_P{1536, 2048};
constexpr gfx::Size kQHD{2560, 1440};
// Chell
constexpr gfx::Size kQHD_PLUS{3200, 1800};
constexpr gfx::Size kUHD{3840, 2160};
// Chromebook special panels
constexpr gfx::Size kLux{2160, 1440};
constexpr gfx::Size kAkaliQHD{2256, 1504};
constexpr gfx::Size kLink{2560, 1700};
constexpr gfx::Size kEveDisplay{2400, 1600};
constexpr gfx::Size kNocturne{3000, 2000};
enum SizeErrorCheckType {
kExact, // Exact match.
kEpsilon, // Matches within epsilon.
kSkip, // Skip testing the error.
};
constexpr struct Data {
const float diagonal_size;
const gfx::Size resolution;
const float expected_dsf;
const gfx::Size expected_dp_size;
const bool bad_range;
const SizeErrorCheckType screenshot_size_error;
} display_configs[] = {
// clang-format off
// inch, resolution, DSF, size in DP, Bad range, size error
{10.1f, kWXGA_800, 1.f, kWXGA_800, false, kExact},
{12.1f, kWXGA_800, 1.f, kWXGA_800, true, kExact},
{11.6f, kWXGA_768, 1.f, kWXGA_768, false, kExact},
{13.3f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{14.f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{15.6f, kWXGA_768, 1.f, kWXGA_768, true, kExact},
{9.7f, kQXGA_P, 2.0f, {768, 1024}, false, kExact},
{11.6f, kFHD, 1.6f, {1200, 675}, false, kExact},
{13.0f, kFHD, 1.25f, {1536, 864}, true, kExact},
{13.3f, kFHD, 1.25f, {1536, 864}, true, kExact},
{14.f, kFHD, 1.25f, {1536, 864}, false, kExact},
{10.1f, kWUXGA, kDsf_1_777, {1080, 675}, false, kExact},
{12.2f, kWUXGA, 1.6f, {1200, 750}, false, kExact},
{15.6f, kWUXGA, 1.f, kWUXGA, false, kExact},
{12.3f, kQHD, 2.f, {1280, 720}, false, kExact},
// Non standard panels
{11.0f, kLux, 2.f, {1080, 720}, false, kExact},
{12.02f, kLux, 1.6f, {1350, 900}, true, kExact},
{13.3f, kQHD_PLUS, 2.f, {1600, 900}, false, kSkip},
{13.3f, kAkaliQHD, 1.6f, {1410, 940}, false, kExact},
{12.3f, kEveDisplay,2.0f, {1200, 800}, false, kExact},
{12.85f, kLink, 2.0f, {1280, 850}, false, kExact},
{12.3f, kNocturne, kDsf_2_252, {1332, 888}, false, kEpsilon},
{13.1f, kUHD, kDsf_2_666, {1440, 810}, false, kExact},
{15.6f, kUHD, 2.4f, {1600, 900}, false, kEpsilon},
// Chromebase
{19.5, kHD_PLUS, 1.f, kHD_PLUS, true, kExact},
{21.5f, kFHD, 1.f, kFHD, true, kExact},
{23.8f, kFHD, 1.f, kFHD, true, kExact},
// clang-format on
};
} // namespace display
#endif // UI_DISPLAY_TYPES_DISPLAY_CONSTANTS_H_
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