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> |
(...skipping 12 matching lines...) Expand all Loading... | |
23 | 23 |
24 namespace chromeos { | 24 namespace chromeos { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 // DPI measurements. | 28 // DPI measurements. |
29 const float kMmInInch = 25.4; | 29 const float kMmInInch = 25.4; |
30 const float kDpi96 = 96.0; | 30 const float kDpi96 = 96.0; |
31 const float kPixelsToMmScale = kMmInInch / kDpi96; | 31 const float kPixelsToMmScale = kMmInInch / kDpi96; |
32 | 32 |
33 // Prefixes of putput name | |
34 const char kOutputPortName_VGA[] = "VGA"; | |
35 const char kOutputPortName_HDMI[] = "HDMI"; | |
36 const char kOutputPortName_DVI[] = "DVI"; | |
37 const char kOutputPortName_DisplayPort[] = "DP"; | |
38 | |
33 bool IsInternalOutput(const XRROutputInfo* output_info) { | 39 bool IsInternalOutput(const XRROutputInfo* output_info) { |
34 return IsInternalOutputName(std::string(output_info->name)); | 40 return IsInternalOutputName(std::string(output_info->name)); |
35 } | 41 } |
36 | 42 |
37 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { | 43 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { |
38 return output_info->nmode > 0 ? output_info->modes[0] : None; | 44 return output_info->nmode > 0 ? output_info->modes[0] : None; |
39 } | 45 } |
40 | 46 |
41 } // namespace | 47 } // namespace |
42 | 48 |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 &mode_info.interlaced)) { | 369 &mode_info.interlaced)) { |
364 output.mode_infos.insert(std::make_pair(mode, mode_info)); | 370 output.mode_infos.insert(std::make_pair(mode, mode_info)); |
365 } else { | 371 } else { |
366 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; | 372 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; |
367 } | 373 } |
368 } | 374 } |
369 | 375 |
370 return output; | 376 return output; |
371 } | 377 } |
372 | 378 |
379 bool RealOutputConfiguratorDelegate::GetHDCPState(RROutput id, | |
380 HDCPState* state) { | |
381 CHECK(screen_) << "Server not grabbed"; | |
382 unsigned char* values = NULL; | |
383 int actual_format; | |
384 unsigned long nitems; | |
385 unsigned long bytes_after; | |
386 Atom actual_type; | |
387 int success; | |
dmichael (off chromium)
2013/09/09 20:37:15
please initialize these (same for other variables
kcwu
2013/09/10 12:50:21
Done.
| |
388 Atom prop = XInternAtom(display_, "Content Protection", False); | |
389 | |
390 bool ok = true; | |
391 success = XRRGetOutputProperty(display_, id, prop, 0, 100, False, | |
392 False, AnyPropertyType, &actual_type, | |
393 &actual_format, &nitems, &bytes_after, | |
394 &values); | |
395 if (actual_type == None) { | |
396 LOG(ERROR) << "Property 'Content Protection' does not exist"; | |
397 ok = false; | |
398 } else if (success == Success && actual_type == XA_ATOM && | |
399 actual_format == 32 && nitems == 1) { | |
400 Atom value = reinterpret_cast<Atom*>(values)[0]; | |
401 if (value == XInternAtom(display_, "Undesired", False)) | |
402 *state = HDCP_State_Undesired; | |
403 else if (value == XInternAtom(display_, "Desired", False)) | |
404 *state = HDCP_State_Desired; | |
405 else if (value == XInternAtom(display_, "Enabled", False)) | |
406 *state = HDCP_State_Enabled; | |
407 else { | |
408 LOG(ERROR) << "Unknown property value: " << value; | |
409 ok = false; | |
410 } | |
411 } else { | |
412 LOG(ERROR) << "XRRGetOutputProperty failed"; | |
413 ok = false; | |
414 } | |
415 if (values) | |
416 XFree(values); | |
417 | |
418 VLOG(3) << "HDCP state: " << ok << "," << *state; | |
419 return ok; | |
420 } | |
421 | |
422 bool RealOutputConfiguratorDelegate::SetHDCPState(RROutput id, | |
423 HDCPState state) { | |
424 CHECK(screen_) << "Server not grabbed"; | |
425 Atom name = XInternAtom(display_, "Content Protection", False); | |
426 unsigned long value; | |
427 switch (state) { | |
428 case HDCP_State_Undesired: | |
429 value = XInternAtom(display_, "Undesired", False); | |
dmichael (off chromium)
2013/09/09 20:37:15
It looks like this function returns type "Atom"...
kcwu
2013/09/10 12:50:21
Done.
| |
430 break; | |
431 case HDCP_State_Desired: | |
432 value = XInternAtom(display_, "Desired", False); | |
433 break; | |
434 default: | |
435 DCHECK(0) << "Invalid HDCP state: " << state; | |
436 return false; | |
437 } | |
438 unsigned char *data = (unsigned char*)&value; | |
dmichael (off chromium)
2013/09/09 20:37:15
Please do not use C-style casts. I think you want
kcwu
2013/09/10 12:50:21
Done.
kcwu
2013/09/10 12:50:21
Done.
| |
439 XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32, | |
440 PropModeReplace, data, 1); | |
441 return true; | |
442 } | |
443 | |
444 bool DetermineLinkType(const XRROutputInfo* output_info, | |
dmichael (off chromium)
2013/09/09 20:37:15
const-reference?
kcwu
2013/09/10 12:50:21
Existing code, IsInternalOutput() takes const-poin
dmichael (off chromium)
2013/09/11 18:22:45
Yes. It looks like IsInternalOutput assumes that t
kcwu
2013/09/12 18:22:08
Done.
| |
445 PP_OutputProtectionLinkType_Private* link_type) { | |
446 std::string name(output_info->name); | |
447 if (IsInternalOutput(output_info)) { | |
448 *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL; | |
449 } else if (name.find(kOutputPortName_VGA) == 0) { | |
450 *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA; | |
451 } else if (name.find(kOutputPortName_HDMI) == 0) { | |
452 *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI; | |
453 } else if (name.find(kOutputPortName_DisplayPort) == 0) { | |
454 *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT; | |
455 } else { | |
456 DCHECK(0) << "Unknown link type: " << name; | |
457 return false; | |
458 } | |
459 return true; | |
460 } | |
461 | |
462 bool RealOutputConfiguratorDelegate::GetOutputLinkType( | |
dmichael (off chromium)
2013/09/09 20:37:15
Type->Types? It looks like you can retrieve more t
kcwu
2013/09/10 12:50:21
Done.
| |
463 std::vector<PP_OutputProtectionLinkType_Private>& link_type) { | |
dmichael (off chromium)
2013/09/09 20:37:15
out-params should be by pointer:
http://google-sty
kcwu
2013/09/10 12:50:21
Done.
| |
464 CHECK(screen_) << "Server not grabbed"; | |
465 bool result = true; | |
466 for (int i = 0; i < screen_->noutput; ++i) { | |
467 RROutput this_id = screen_->outputs[i]; | |
468 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, this_id); | |
dmichael (off chromium)
2013/09/09 20:37:15
Can this return NULL? It looks like it can:
http:/
kcwu
2013/09/10 12:50:21
Done.
BTW, this is copied from existing code, line
| |
469 if (output_info->connection != RR_Connected) { | |
470 XRRFreeOutputInfo(output_info); | |
dmichael (off chromium)
2013/09/09 20:37:15
optional suggestion: You could use scoped_ptr<XRRO
kcwu
2013/09/10 12:50:21
Done.
| |
471 link_type.push_back(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE); | |
472 continue; | |
dmichael (off chromium)
2013/09/09 20:37:15
Why not just use an else? And I'd maybe flip the c
kcwu
2013/09/10 12:50:21
Done.
| |
473 } | |
474 | |
475 PP_OutputProtectionLinkType_Private type; | |
476 if (DetermineLinkType(output_info, &type)) | |
477 link_type.push_back(type); | |
478 else | |
479 result = false; | |
480 XRRFreeOutputInfo(output_info); | |
481 } | |
482 return result; | |
483 } | |
484 | |
485 bool RealOutputConfiguratorDelegate::GetOutputLinkMask(uint32_t* link_mask) { | |
486 std::vector<PP_OutputProtectionLinkType_Private> link_type; | |
487 *link_mask = 0; | |
488 if (!GetOutputLinkType(link_type)) | |
489 return false; | |
490 | |
491 for (std::vector<PP_OutputProtectionLinkType_Private>::const_iterator it = | |
492 link_type.begin(); it != link_type.end(); ++it) { | |
493 *link_mask |= *it; | |
494 } | |
495 return true; | |
496 } | |
497 | |
498 bool RealOutputConfiguratorDelegate::GetProtectionMethods( | |
499 uint32_t* protection_mask) { | |
500 CHECK(screen_) << "Server not grabbed"; | |
501 std::vector<PP_OutputProtectionLinkType_Private> link_type; | |
502 if (!GetOutputLinkType(link_type)) | |
503 return false; | |
504 | |
505 uint32_t enabled = 0; | |
506 uint32_t unfulfiled = 0; | |
507 | |
508 DCHECK(screen_->noutput == (int)link_type.size()); | |
dmichael (off chromium)
2013/09/09 20:37:15
no C-style casts
http://google-styleguide.googleco
kcwu
2013/09/10 12:50:21
Done.
dmichael (off chromium)
2013/09/11 18:22:45
nit: It's usually better to static_cast the type t
kcwu
2013/09/12 18:22:08
Use DCHECK_EQ() instead as Dale suggested.
| |
509 for (int i = 0; i < screen_->noutput; ++i) { | |
510 PP_OutputProtectionLinkType_Private type = link_type[i]; | |
511 if (type & (PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI | | |
512 PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) { | |
dmichael (off chromium)
2013/09/09 20:37:15
optional nit: I would find it more readable as:
if
kcwu
2013/09/10 12:50:21
Done.
| |
513 HDCPState state; | |
514 RROutput this_id = screen_->outputs[i]; | |
515 if (!GetHDCPState(this_id, &state)) | |
516 return false; | |
517 if (state == HDCP_State_Enabled) | |
518 enabled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP; | |
519 else | |
520 unfulfiled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP; | |
521 } | |
522 } | |
523 *protection_mask = enabled & ~unfulfiled; | |
dmichael (off chromium)
2013/09/09 20:37:15
I don't really understand the APIs we're using...
kcwu
2013/09/10 12:50:21
Yes, content owner would like to playback their co
| |
524 return true; | |
525 } | |
526 | |
527 uint32_t RealOutputConfiguratorDelegate::GetCombinedProtectionRequest() { | |
528 uint32_t combined_requirement = 0; | |
529 for (ProtectionRequests::const_iterator it = | |
530 client_protection_request_.begin(); | |
531 it != client_protection_request_.end(); | |
532 ++it) { | |
533 combined_requirement |= it->second; | |
534 } | |
535 return combined_requirement; | |
536 } | |
537 | |
538 bool RealOutputConfiguratorDelegate::EnableOutputProtection( | |
539 chrome::PepperOutputProtectionHost* client, uint32_t desired_method_mask) { | |
540 if (desired_method_mask == PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE) | |
541 client_protection_request_.erase(client); | |
542 else | |
543 client_protection_request_[client] = desired_method_mask; | |
544 | |
545 uint32_t all_desires = GetCombinedProtectionRequest(); | |
546 std::vector<PP_OutputProtectionLinkType_Private> link_type; | |
547 if (!GetOutputLinkType(link_type)) | |
dmichael (off chromium)
2013/09/09 20:37:15
You do this a lot. Might it make sense to have som
kcwu
2013/09/10 12:50:21
Right. It is not used otherwhere GrabServer is.
An
| |
548 return false; | |
549 bool ok = true; | |
550 for (int i = 0; i < screen_->noutput; ++i) { | |
551 RROutput this_id = screen_->outputs[i]; | |
552 PP_OutputProtectionLinkType_Private type = link_type[i]; | |
553 if (type & (PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI | | |
554 PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) { | |
dmichael (off chromium)
2013/09/09 20:37:15
ditto, I somewhat prefer separate bit masking and
kcwu
2013/09/10 12:50:21
Done.
| |
555 if (all_desires & PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) { | |
556 ok = SetHDCPState(this_id, HDCP_State_Desired); | |
557 } else { | |
558 ok = SetHDCPState(this_id, HDCP_State_Undesired); | |
559 } | |
560 } | |
561 | |
562 if (!ok) | |
563 return false; | |
564 } | |
565 return true; | |
566 } | |
567 | |
568 bool RealOutputConfiguratorDelegate::QueryOutputProtectionStatus( | |
569 chrome::PepperOutputProtectionHost* client, | |
570 uint32_t* link_mask, | |
571 uint32_t* protection_mask) { | |
572 bool ok = GetProtectionMethods(protection_mask) && | |
573 GetOutputLinkMask(link_mask); | |
dmichael (off chromium)
2013/09/09 20:37:15
nit: 4-space indent
kcwu
2013/09/10 12:50:21
Done.
| |
574 ProtectionRequests::iterator it = client_protection_request_.find(client); | |
575 | |
576 // Don't reveal protections requested by other clients. | |
577 if (it != client_protection_request_.end()) { | |
578 *protection_mask &= it->second; | |
579 } else { | |
580 *protection_mask = 0; | |
581 } | |
582 return ok; | |
583 } | |
584 | |
373 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( | 585 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( |
374 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { | 586 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { |
375 CHECK(screen_) << "Server not grabbed"; | 587 CHECK(screen_) << "Server not grabbed"; |
376 // Setting the screen size will fail if any CRTC doesn't fit afterwards. | 588 // Setting the screen size will fail if any CRTC doesn't fit afterwards. |
377 // At the same time, turning CRTCs off and back on uses up a lot of time. | 589 // At the same time, turning CRTCs off and back on uses up a lot of time. |
378 // This function tries to be smart to avoid too many off/on cycles: | 590 // This function tries to be smart to avoid too many off/on cycles: |
379 // - We disable all the CRTCs we won't need after the FB resize. | 591 // - We disable all the CRTCs we won't need after the FB resize. |
380 // - We set the new modes on CRTCs, if they fit in both the old and new | 592 // - We set the new modes on CRTCs, if they fit in both the old and new |
381 // FBs, and park them at (0,0) | 593 // FBs, and park them at (0,0) |
382 // - We disable the CRTCs we will need but don't fit in the old FB. Those | 594 // - We disable the CRTCs we will need but don't fit in the old FB. Those |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
638 << (*outputs)[i].touch_device_id << " to output #" << i; | 850 << (*outputs)[i].touch_device_id << " to output #" << i; |
639 break; | 851 break; |
640 } | 852 } |
641 } | 853 } |
642 } | 854 } |
643 | 855 |
644 XIFreeDeviceInfo(info); | 856 XIFreeDeviceInfo(info); |
645 } | 857 } |
646 | 858 |
647 } // namespace chromeos | 859 } // namespace chromeos |
OLD | NEW |