OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chromeos/display/real_output_configurator_delegate.h" | 5 #include "chromeos/display/real_output_configurator_delegate.h" |
6 | 6 |
7 #include <X11/Xatom.h> | 7 #include <X11/Xatom.h> |
8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
9 #include <X11/extensions/dpms.h> | 9 #include <X11/extensions/dpms.h> |
10 #include <X11/extensions/XInput.h> | 10 #include <X11/extensions/XInput.h> |
11 #include <X11/extensions/XInput2.h> | 11 #include <X11/extensions/XInput2.h> |
12 #include <X11/extensions/Xrandr.h> | 12 #include <X11/extensions/Xrandr.h> |
13 | 13 |
14 #include <cmath> | 14 #include <cmath> |
15 #include <set> | 15 #include <set> |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/message_loop/message_pump_x11.h" | 19 #include "base/message_loop/message_pump_x11.h" |
20 #include "base/x11/edid_parser_x11.h" | 20 #include "base/x11/edid_parser_x11.h" |
| 21 #include "base/x11/x11_error_tracker.h" |
21 #include "chromeos/dbus/dbus_thread_manager.h" | 22 #include "chromeos/dbus/dbus_thread_manager.h" |
22 #include "chromeos/dbus/power_manager_client.h" | 23 #include "chromeos/dbus/power_manager_client.h" |
23 #include "chromeos/display/output_util.h" | 24 #include "chromeos/display/output_util.h" |
24 | 25 |
25 namespace chromeos { | 26 namespace chromeos { |
26 | 27 |
27 namespace { | 28 namespace { |
28 | 29 |
29 // DPI measurements. | 30 // DPI measurements. |
30 const float kMmInInch = 25.4; | 31 const float kMmInInch = 25.4; |
31 const float kDpi96 = 96.0; | 32 const float kDpi96 = 96.0; |
32 const float kPixelsToMmScale = kMmInInch / kDpi96; | 33 const float kPixelsToMmScale = kMmInInch / kDpi96; |
33 | 34 |
| 35 // Prefixes of output name |
| 36 const char kOutputName_VGA[] = "VGA"; |
| 37 const char kOutputName_HDMI[] = "HDMI"; |
| 38 const char kOutputName_DVI[] = "DVI"; |
| 39 const char kOutputName_DisplayPort[] = "DP"; |
| 40 |
| 41 const char kContentProtectionAtomName[] = "Content Protection"; |
| 42 const char kProtectionUndesiredAtomName[] = "Undesired"; |
| 43 const char kProtectionDesiredAtomName[] = "Desired"; |
| 44 const char kProtectionEnabledAtomName[] = "Enabled"; |
| 45 |
34 bool IsInternalOutput(const XRROutputInfo* output_info) { | 46 bool IsInternalOutput(const XRROutputInfo* output_info) { |
35 return IsInternalOutputName(std::string(output_info->name)); | 47 return IsInternalOutputName(std::string(output_info->name)); |
36 } | 48 } |
37 | 49 |
38 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { | 50 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { |
39 return output_info->nmode > 0 ? output_info->modes[0] : None; | 51 return output_info->nmode > 0 ? output_info->modes[0] : None; |
40 } | 52 } |
41 | 53 |
42 } // namespace | 54 } // namespace |
43 | 55 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 | 309 |
298 for (int i = 0; i < info->nmode; ++i) { | 310 for (int i = 0; i < info->nmode; ++i) { |
299 const RRMode mode = info->modes[i]; | 311 const RRMode mode = info->modes[i]; |
300 OutputConfigurator::ModeInfo mode_info; | 312 OutputConfigurator::ModeInfo mode_info; |
301 if (InitModeInfo(mode, &mode_info)) | 313 if (InitModeInfo(mode, &mode_info)) |
302 output.mode_infos.insert(std::make_pair(mode, mode_info)); | 314 output.mode_infos.insert(std::make_pair(mode, mode_info)); |
303 else | 315 else |
304 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; | 316 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; |
305 } | 317 } |
306 | 318 |
| 319 std::string name(info->name); |
| 320 if (output.is_internal) { |
| 321 output.type = OUTPUT_TYPE_INTERNAL; |
| 322 } else if (name.find(kOutputName_VGA) == 0) { |
| 323 output.type = OUTPUT_TYPE_VGA; |
| 324 } else if (name.find(kOutputName_HDMI) == 0) { |
| 325 output.type = OUTPUT_TYPE_HDMI; |
| 326 } else if (name.find(kOutputName_DVI) == 0) { |
| 327 output.type = OUTPUT_TYPE_DVI; |
| 328 } else if (name.find(kOutputName_DisplayPort) == 0) { |
| 329 output.type = OUTPUT_TYPE_DISPLAYPORT; |
| 330 } else { |
| 331 LOG(ERROR) << "Unknown link type: " << name; |
| 332 output.type = OUTPUT_TYPE_UNKNOWN; |
| 333 } |
| 334 |
307 return output; | 335 return output; |
308 } | 336 } |
309 | 337 |
| 338 bool RealOutputConfiguratorDelegate::GetHDCPState(RROutput id, |
| 339 HDCPState* state) { |
| 340 unsigned char* values = NULL; |
| 341 int actual_format = 0; |
| 342 unsigned long nitems = 0; |
| 343 unsigned long bytes_after = 0; |
| 344 Atom actual_type = None; |
| 345 int success = 0; |
| 346 // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom. |
| 347 Atom prop = XInternAtom(display_, kContentProtectionAtomName, False); |
| 348 |
| 349 bool ok = true; |
| 350 // TODO(kcwu): Move this to x11_util (similar method calls in this file and |
| 351 // output_util.cc) |
| 352 success = XRRGetOutputProperty(display_, id, prop, 0, 100, False, |
| 353 False, AnyPropertyType, &actual_type, |
| 354 &actual_format, &nitems, &bytes_after, |
| 355 &values); |
| 356 if (actual_type == None) { |
| 357 LOG(ERROR) << "Property '" << kContentProtectionAtomName |
| 358 << "' does not exist"; |
| 359 ok = false; |
| 360 } else if (success == Success && actual_type == XA_ATOM && |
| 361 actual_format == 32 && nitems == 1) { |
| 362 Atom value = reinterpret_cast<Atom*>(values)[0]; |
| 363 if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) { |
| 364 *state = HDCP_STATE_UNDESIRED; |
| 365 } else if (value == XInternAtom(display_, kProtectionDesiredAtomName, |
| 366 False)) { |
| 367 *state = HDCP_STATE_DESIRED; |
| 368 } else if (value == XInternAtom(display_, kProtectionEnabledAtomName, |
| 369 False)) { |
| 370 *state = HDCP_STATE_ENABLED; |
| 371 } else { |
| 372 LOG(ERROR) << "Unknown " << kContentProtectionAtomName << " value: " |
| 373 << value; |
| 374 ok = false; |
| 375 } |
| 376 } else { |
| 377 LOG(ERROR) << "XRRGetOutputProperty failed"; |
| 378 ok = false; |
| 379 } |
| 380 if (values) |
| 381 XFree(values); |
| 382 |
| 383 VLOG(3) << "HDCP state: " << ok << "," << *state; |
| 384 return ok; |
| 385 } |
| 386 |
| 387 bool RealOutputConfiguratorDelegate::SetHDCPState(RROutput id, |
| 388 HDCPState state) { |
| 389 Atom name = XInternAtom(display_, kContentProtectionAtomName, False); |
| 390 Atom value = None; |
| 391 switch (state) { |
| 392 case HDCP_STATE_UNDESIRED: |
| 393 value = XInternAtom(display_, kProtectionUndesiredAtomName, False); |
| 394 break; |
| 395 case HDCP_STATE_DESIRED: |
| 396 value = XInternAtom(display_, kProtectionDesiredAtomName, False); |
| 397 break; |
| 398 default: |
| 399 NOTREACHED() << "Invalid HDCP state: " << state; |
| 400 return false; |
| 401 } |
| 402 base::X11ErrorTracker err_tracker; |
| 403 unsigned char* data = reinterpret_cast<unsigned char*>(&value); |
| 404 XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32, |
| 405 PropModeReplace, data, 1); |
| 406 if (err_tracker.FoundNewError()) { |
| 407 LOG(ERROR) << "XRRChangeOutputProperty failed"; |
| 408 return false; |
| 409 } else { |
| 410 return true; |
| 411 } |
| 412 } |
| 413 |
310 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( | 414 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( |
311 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { | 415 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { |
312 CHECK(screen_) << "Server not grabbed"; | 416 CHECK(screen_) << "Server not grabbed"; |
313 // Setting the screen size will fail if any CRTC doesn't fit afterwards. | 417 // Setting the screen size will fail if any CRTC doesn't fit afterwards. |
314 // At the same time, turning CRTCs off and back on uses up a lot of time. | 418 // At the same time, turning CRTCs off and back on uses up a lot of time. |
315 // This function tries to be smart to avoid too many off/on cycles: | 419 // This function tries to be smart to avoid too many off/on cycles: |
316 // - We disable all the CRTCs we won't need after the FB resize. | 420 // - We disable all the CRTCs we won't need after the FB resize. |
317 // - We set the new modes on CRTCs, if they fit in both the old and new | 421 // - We set the new modes on CRTCs, if they fit in both the old and new |
318 // FBs, and park them at (0,0) | 422 // FBs, and park them at (0,0) |
319 // - We disable the CRTCs we will need but don't fit in the old FB. Those | 423 // - We disable the CRTCs we will need but don't fit in the old FB. Those |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 << (*outputs)[i].touch_device_id << " to output #" << i; | 605 << (*outputs)[i].touch_device_id << " to output #" << i; |
502 break; | 606 break; |
503 } | 607 } |
504 } | 608 } |
505 } | 609 } |
506 | 610 |
507 XIFreeDeviceInfo(info); | 611 XIFreeDeviceInfo(info); |
508 } | 612 } |
509 | 613 |
510 } // namespace chromeos | 614 } // namespace chromeos |
OLD | NEW |