display.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/display/display.h"
  5. #include <algorithm>
  6. #include "base/command_line.h"
  7. #include "base/containers/contains.h"
  8. #include "base/logging.h"
  9. #include "base/notreached.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "build/build_config.h"
  13. #include "ui/display/display_switches.h"
  14. #include "ui/display/util/display_util.h"
  15. #include "ui/gfx/geometry/insets.h"
  16. #include "ui/gfx/geometry/rect_conversions.h"
  17. #include "ui/gfx/geometry/rect_f.h"
  18. #include "ui/gfx/geometry/transform.h"
  19. #include "ui/gfx/icc_profile.h"
  20. namespace display {
  21. namespace {
  22. // This variable tracks whether the forced device scale factor switch needs to
  23. // be read from the command line, i.e. if it is set to -1 then the command line
  24. // is checked.
  25. int g_has_forced_device_scale_factor = -1;
  26. // This variable caches the forced device scale factor value which is read off
  27. // the command line. If the cache is invalidated by setting this variable to
  28. // -1.0, we read the forced device scale factor again.
  29. float g_forced_device_scale_factor = -1.0;
  30. // An allowance error epsilon caused by fractional scale factor to produce
  31. // expected DP display size.
  32. constexpr float kDisplaySizeAllowanceEpsilon = 0.01f;
  33. bool HasForceDeviceScaleFactorImpl() {
  34. return base::CommandLine::ForCurrentProcess()->HasSwitch(
  35. switches::kForceDeviceScaleFactor);
  36. }
  37. float GetForcedDeviceScaleFactorImpl() {
  38. double scale_in_double = 1.0;
  39. if (HasForceDeviceScaleFactorImpl()) {
  40. std::string value =
  41. base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
  42. switches::kForceDeviceScaleFactor);
  43. if (!base::StringToDouble(value, &scale_in_double)) {
  44. LOG(ERROR) << "Failed to parse the default device scale factor:" << value;
  45. scale_in_double = 1.0;
  46. }
  47. }
  48. return static_cast<float>(scale_in_double);
  49. }
  50. const char* ToRotationString(display::Display::Rotation rotation) {
  51. switch (rotation) {
  52. case display::Display::ROTATE_0:
  53. return "0";
  54. case display::Display::ROTATE_90:
  55. return "90";
  56. case display::Display::ROTATE_180:
  57. return "180";
  58. case display::Display::ROTATE_270:
  59. return "270";
  60. }
  61. NOTREACHED();
  62. return "unkonwn";
  63. }
  64. } // namespace
  65. // static
  66. float Display::GetForcedDeviceScaleFactor() {
  67. if (g_forced_device_scale_factor < 0)
  68. g_forced_device_scale_factor = GetForcedDeviceScaleFactorImpl();
  69. return g_forced_device_scale_factor;
  70. }
  71. // static
  72. bool Display::HasForceDeviceScaleFactor() {
  73. if (g_has_forced_device_scale_factor == -1)
  74. g_has_forced_device_scale_factor = HasForceDeviceScaleFactorImpl();
  75. return !!g_has_forced_device_scale_factor;
  76. }
  77. // static
  78. void Display::ResetForceDeviceScaleFactorForTesting() {
  79. g_has_forced_device_scale_factor = -1;
  80. g_forced_device_scale_factor = -1.0;
  81. }
  82. // static
  83. void Display::SetForceDeviceScaleFactor(double dsf) {
  84. // Reset any previously set values and unset the flag.
  85. g_has_forced_device_scale_factor = -1;
  86. g_forced_device_scale_factor = -1.0;
  87. base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
  88. switches::kForceDeviceScaleFactor, base::StringPrintf("%.2f", dsf));
  89. }
  90. // static
  91. gfx::ColorSpace Display::GetForcedRasterColorProfile() {
  92. DCHECK(HasForceRasterColorProfile());
  93. std::string value =
  94. base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
  95. switches::kForceRasterColorProfile);
  96. return ForcedColorProfileStringToColorSpace(value);
  97. }
  98. // static
  99. bool Display::HasForceRasterColorProfile() {
  100. return base::CommandLine::ForCurrentProcess()->HasSwitch(
  101. switches::kForceRasterColorProfile);
  102. }
  103. // static
  104. bool Display::HasEnsureForcedColorProfile() {
  105. static bool has_ensure_forced_color_profile =
  106. base::CommandLine::ForCurrentProcess()->HasSwitch(
  107. switches::kEnsureForcedColorProfile);
  108. return has_ensure_forced_color_profile;
  109. }
  110. // static
  111. display::Display::Rotation Display::DegreesToRotation(int degrees) {
  112. if (degrees == 0)
  113. return display::Display::ROTATE_0;
  114. if (degrees == 90)
  115. return display::Display::ROTATE_90;
  116. if (degrees == 180)
  117. return display::Display::ROTATE_180;
  118. if (degrees == 270)
  119. return display::Display::ROTATE_270;
  120. NOTREACHED();
  121. return display::Display::ROTATE_0;
  122. }
  123. // static
  124. int Display::RotationToDegrees(display::Display::Rotation rotation) {
  125. switch (rotation) {
  126. case display::Display::ROTATE_0:
  127. return 0;
  128. case display::Display::ROTATE_90:
  129. return 90;
  130. case display::Display::ROTATE_180:
  131. return 180;
  132. case display::Display::ROTATE_270:
  133. return 270;
  134. }
  135. NOTREACHED();
  136. return 0;
  137. }
  138. // static
  139. bool Display::IsValidRotation(int degrees) {
  140. return degrees == 0 || degrees == 90 || degrees == 180 || degrees == 270;
  141. }
  142. Display::Display() : Display(kInvalidDisplayId) {}
  143. Display::Display(int64_t id) : Display(id, gfx::Rect()) {}
  144. Display::Display(int64_t id, const gfx::Rect& bounds)
  145. : id_(id),
  146. bounds_(bounds),
  147. work_area_(bounds),
  148. device_scale_factor_(GetForcedDeviceScaleFactor()) {
  149. // On Android we need to ensure the platform supports a color profile before
  150. // using it. Using a not supported profile can result in fatal errors in the
  151. // GPU process.
  152. auto color_space = gfx::ColorSpace::CreateSRGB();
  153. #if !BUILDFLAG(IS_ANDROID)
  154. if (HasForceDisplayColorProfile())
  155. color_space = GetForcedDisplayColorProfile();
  156. #endif
  157. color_spaces_ = gfx::DisplayColorSpaces(color_space);
  158. if (color_spaces_.SupportsHDR()) {
  159. color_depth_ = kHDR10BitsPerPixel;
  160. depth_per_component_ = kHDR10BitsPerComponent;
  161. } else {
  162. color_depth_ = kDefaultBitsPerPixel;
  163. depth_per_component_ = kDefaultBitsPerComponent;
  164. }
  165. #if defined(USE_AURA)
  166. if (!bounds.IsEmpty())
  167. SetScaleAndBounds(device_scale_factor_, bounds);
  168. #endif
  169. }
  170. Display::Display(const Display& other) = default;
  171. Display::~Display() {}
  172. // static
  173. Display Display::GetDefaultDisplay() {
  174. return Display(kDefaultDisplayId, gfx::Rect(0, 0, 1920, 1080));
  175. }
  176. int Display::RotationAsDegree() const {
  177. switch (rotation_) {
  178. case ROTATE_0:
  179. return 0;
  180. case ROTATE_90:
  181. return 90;
  182. case ROTATE_180:
  183. return 180;
  184. case ROTATE_270:
  185. return 270;
  186. }
  187. NOTREACHED();
  188. return 0;
  189. }
  190. void Display::set_color_spaces(const gfx::DisplayColorSpaces& color_spaces) {
  191. color_spaces_ = color_spaces;
  192. if (color_spaces.SupportsHDR()) {
  193. color_depth_ = kHDR10BitsPerPixel;
  194. depth_per_component_ = kHDR10BitsPerComponent;
  195. } else {
  196. color_depth_ = kDefaultBitsPerPixel;
  197. depth_per_component_ = kDefaultBitsPerComponent;
  198. }
  199. }
  200. void Display::SetRotationAsDegree(int rotation) {
  201. switch (rotation) {
  202. case 0:
  203. rotation_ = ROTATE_0;
  204. break;
  205. case 90:
  206. rotation_ = ROTATE_90;
  207. break;
  208. case 180:
  209. rotation_ = ROTATE_180;
  210. break;
  211. case 270:
  212. rotation_ = ROTATE_270;
  213. break;
  214. default:
  215. // We should not reach that but we will just ignore the call if we do.
  216. NOTREACHED();
  217. }
  218. }
  219. int Display::PanelRotationAsDegree() const {
  220. return RotationToDegrees(panel_rotation());
  221. }
  222. gfx::Insets Display::GetWorkAreaInsets() const {
  223. return gfx::Insets::TLBR(work_area_.y() - bounds_.y(),
  224. work_area_.x() - bounds_.x(),
  225. bounds_.bottom() - work_area_.bottom(),
  226. bounds_.right() - work_area_.right());
  227. }
  228. void Display::SetScaleAndBounds(float device_scale_factor,
  229. const gfx::Rect& bounds_in_pixel) {
  230. gfx::Insets insets = bounds_.InsetsFrom(work_area_);
  231. SetScale(device_scale_factor);
  232. gfx::RectF f(bounds_in_pixel);
  233. f.Scale(1.f / device_scale_factor_);
  234. bounds_ = gfx::ToEnclosedRectIgnoringError(f, kDisplaySizeAllowanceEpsilon);
  235. size_in_pixels_ = bounds_in_pixel.size();
  236. UpdateWorkAreaFromInsets(insets);
  237. }
  238. void Display::SetScale(float device_scale_factor) {
  239. if (!HasForceDeviceScaleFactor()) {
  240. #if BUILDFLAG(IS_APPLE)
  241. // Unless an explicit scale factor was provided for testing, ensure the
  242. // scale is integral.
  243. device_scale_factor = static_cast<int>(device_scale_factor);
  244. #endif
  245. device_scale_factor_ = device_scale_factor;
  246. }
  247. device_scale_factor_ = std::max(0.5f, device_scale_factor_);
  248. }
  249. void Display::SetSize(const gfx::Size& size_in_pixel) {
  250. gfx::Point origin = bounds_.origin();
  251. #if defined(USE_AURA)
  252. origin = gfx::ScaleToFlooredPoint(origin, device_scale_factor_);
  253. #endif
  254. SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel));
  255. }
  256. void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) {
  257. work_area_ = bounds_;
  258. work_area_.Inset(insets);
  259. }
  260. gfx::Size Display::GetSizeInPixel() const {
  261. if (!size_in_pixels_.IsEmpty())
  262. return size_in_pixels_;
  263. return gfx::ScaleToFlooredSize(size(), device_scale_factor_);
  264. }
  265. std::string Display::ToString() const {
  266. return base::StringPrintf(
  267. "Display[%lld] bounds=[%s], workarea=[%s], scale=%g, rotation=%s, "
  268. "panel_rotation=%s %s.",
  269. static_cast<long long int>(id_), bounds_.ToString().c_str(),
  270. work_area_.ToString().c_str(), device_scale_factor_,
  271. ToRotationString(rotation_), ToRotationString(panel_rotation()),
  272. IsInternal() ? "internal" : "external");
  273. }
  274. bool Display::IsInternal() const {
  275. return is_valid() && display::IsInternalDisplayId(id_);
  276. }
  277. // static
  278. int64_t Display::InternalDisplayId() {
  279. auto& ids = GetInternalDisplayIds();
  280. DCHECK_EQ(1u, ids.size());
  281. return ids.size() ? *ids.begin() : kInvalidDisplayId;
  282. }
  283. bool Display::operator==(const Display& rhs) const {
  284. return id_ == rhs.id_ && bounds_ == rhs.bounds_ &&
  285. size_in_pixels_ == rhs.size_in_pixels_ &&
  286. work_area_ == rhs.work_area_ &&
  287. device_scale_factor_ == rhs.device_scale_factor_ &&
  288. rotation_ == rhs.rotation_ && touch_support_ == rhs.touch_support_ &&
  289. accelerometer_support_ == rhs.accelerometer_support_ &&
  290. maximum_cursor_size_ == rhs.maximum_cursor_size_ &&
  291. color_spaces_ == rhs.color_spaces_ &&
  292. color_depth_ == rhs.color_depth_ &&
  293. depth_per_component_ == rhs.depth_per_component_ &&
  294. is_monochrome_ == rhs.is_monochrome_ &&
  295. display_frequency_ == rhs.display_frequency_ && label_ == rhs.label_;
  296. }
  297. } // namespace display