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