Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: chromeos/display/real_output_configurator_delegate.cc

Issue 24039002: Pepper API implementation for output protection. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: tweaks conditional compile conditions Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
ddorwin 2013/09/12 04:22:13 output
kcwu 2013/09/12 18:22:08 Done.
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
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";
DaleCurtis 2013/09/12 01:23:13 This will crash the browser process. Do you want t
kcwu 2013/09/12 18:22:08 All checks of screen_ in this file are using CHECK
382 unsigned char* values = NULL;
383 int actual_format = 0;
384 unsigned long nitems = 0;
385 unsigned long bytes_after = 0;
386 Atom actual_type = None;
387 int success = 0;
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 Atom value;
427 switch (state) {
428 case HDCP_State_Undesired:
429 value = XInternAtom(display_, "Undesired", False);
430 break;
431 case HDCP_State_Desired:
432 value = XInternAtom(display_, "Desired", False);
433 break;
434 default:
435 DCHECK(0) << "Invalid HDCP state: " << state;
DaleCurtis 2013/09/12 01:23:13 NOTREACHED() ?
kcwu 2013/09/12 18:22:08 Done.
436 return false;
437 }
438 unsigned char *data = reinterpret_cast<unsigned char*>(&value);
439 XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32,
440 PropModeReplace, data, 1);
441 return true;
442 }
443
444 bool DetermineLinkType(const XRROutputInfo* output_info,
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::GetOutputLinkTypes(
463 std::vector<PP_OutputProtectionLinkType_Private>* link_types) {
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);
DaleCurtis 2013/09/12 01:23:13 How expensive is this query? I ask since it'll be
kcwu 2013/09/12 18:22:08 This query should be very fast. I can measure the
469 if (output_info == NULL) {
470 result = false;
471 break;
472 }
473 if (output_info->connection == RR_Connected) {
dmichael (off chromium) 2013/09/11 18:22:45 you could use "else if" instead of break. I find b
kcwu 2013/09/12 18:22:08 These logic are refactored into separate function,
474 PP_OutputProtectionLinkType_Private type;
475 if (DetermineLinkType(output_info, &type))
476 link_types->push_back(type);
477 else
478 result = false;
DaleCurtis 2013/09/12 01:23:13 Do you want to break here? Should link_types be cl
kcwu 2013/09/12 18:22:08 These logic are refactored into separate function,
479 } else {
480 link_types->push_back(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE);
481 }
482 XRRFreeOutputInfo(output_info);
483 }
484 return result;
485 }
486
487 bool RealOutputConfiguratorDelegate::GetOutputLinkMask(
ddorwin 2013/09/12 04:22:13 This is really a "Convert" function. Also, it coul
kcwu 2013/09/12 18:22:08 These methods are restructured.
488 const std::vector<PP_OutputProtectionLinkType_Private>& link_types,
489 uint32_t* link_mask) {
490 *link_mask = 0;
491
492 for (std::vector<PP_OutputProtectionLinkType_Private>::const_iterator it =
493 link_types.begin(); it != link_types.end(); ++it) {
494 *link_mask |= *it;
495 }
496 return true;
497 }
498
499 bool RealOutputConfiguratorDelegate::GetProtectionMethods(
ddorwin 2013/09/12 04:22:13 This function could easily return the link_mask, s
kcwu 2013/09/12 18:22:08 Done.
500 const std::vector<PP_OutputProtectionLinkType_Private>& link_types,
501 uint32_t* protection_mask) {
502 CHECK(screen_) << "Server not grabbed";
503 uint32_t enabled = 0;
504 uint32_t unfulfiled = 0;
505
506 DCHECK(screen_->noutput == static_cast<int>(link_types.size()));
DaleCurtis 2013/09/12 01:23:13 DCHECK_EQ ?
kcwu 2013/09/12 18:22:08 Done.
507 for (int i = 0; i < screen_->noutput; ++i) {
508 PP_OutputProtectionLinkType_Private type = link_types[i];
509 if ((type & PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) ||
510 (type & PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) {
511 HDCPState state;
512 RROutput this_id = screen_->outputs[i];
513 if (!GetHDCPState(this_id, &state))
514 return false;
515 if (state == HDCP_State_Enabled)
516 enabled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP;
517 else
518 unfulfiled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP;
519 }
520 }
521 *protection_mask = enabled & ~unfulfiled;
522 return true;
523 }
524
525 uint32_t RealOutputConfiguratorDelegate::GetCombinedProtectionRequest() {
526 uint32_t combined_requirement = 0;
527 for (ProtectionRequests::const_iterator it =
528 client_protection_request_.begin();
529 it != client_protection_request_.end();
530 ++it) {
531 combined_requirement |= it->second;
532 }
533 return combined_requirement;
534 }
535
536 bool RealOutputConfiguratorDelegate::EnableOutputProtection(
537 const chrome::PepperOutputProtectionHost* client,
538 uint32_t desired_method_mask) {
539 if (desired_method_mask == PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE)
540 client_protection_request_.erase(client);
541 else
542 client_protection_request_[client] = desired_method_mask;
543
544 uint32_t all_desires = GetCombinedProtectionRequest();
545 std::vector<PP_OutputProtectionLinkType_Private> link_types;
546 if (!GetOutputLinkTypes(&link_types))
ddorwin 2013/09/12 04:22:13 It's odd that we iterate through the outputs to ge
kcwu 2013/09/12 18:22:08 Done. Per this suggestion. These methods are refac
547 return false;
548 bool ok = true;
549 for (int i = 0; i < screen_->noutput; ++i) {
550 RROutput this_id = screen_->outputs[i];
551 PP_OutputProtectionLinkType_Private type = link_types[i];
552 if ((type & PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI) ||
553 (type & PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) {
554 if (all_desires & PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) {
555 ok = SetHDCPState(this_id, HDCP_State_Desired);
556 } else {
557 ok = SetHDCPState(this_id, HDCP_State_Undesired);
558 }
559 }
560
561 if (!ok)
ddorwin 2013/09/12 04:22:13 "&& ok" could just be a condition in the for loop
kcwu 2013/09/12 18:22:08 Done.
562 return false;
563 }
564 return true;
565 }
566
567 bool RealOutputConfiguratorDelegate::QueryOutputProtectionStatus(
568 const chrome::PepperOutputProtectionHost* client,
569 uint32_t* link_mask,
570 uint32_t* protection_mask) {
571 std::vector<PP_OutputProtectionLinkType_Private> link_types;
572 if (!GetOutputLinkTypes(&link_types))
573 return false;
574
575 bool ok = GetProtectionMethods(link_types, protection_mask) &&
576 GetOutputLinkMask(link_types, link_mask);
577 ProtectionRequests::iterator it = client_protection_request_.find(client);
ddorwin 2013/09/12 04:22:13 This should be with the code below (separated by a
kcwu 2013/09/12 18:22:08 Done.
578
579 // Don't reveal protections requested by other clients.
580 if (it != client_protection_request_.end()) {
581 *protection_mask &= it->second;
ddorwin 2013/09/12 04:22:13 It might help to comment or assign |second| to a c
kcwu 2013/09/12 18:22:08 Done.
582 } else {
583 *protection_mask = 0;
ddorwin 2013/09/12 04:22:13 Should this be a NOTREACHED() or can it actually h
kcwu 2013/09/12 18:22:08 This happens if the client Enable(none) and QueryS
584 }
585 return ok;
586 }
587
373 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( 588 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
374 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { 589 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
375 CHECK(screen_) << "Server not grabbed"; 590 CHECK(screen_) << "Server not grabbed";
376 // Setting the screen size will fail if any CRTC doesn't fit afterwards. 591 // 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. 592 // 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: 593 // 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. 594 // - 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 595 // - We set the new modes on CRTCs, if they fit in both the old and new
381 // FBs, and park them at (0,0) 596 // FBs, and park them at (0,0)
382 // - We disable the CRTCs we will need but don't fit in the old FB. Those 597 // - 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
638 << (*outputs)[i].touch_device_id << " to output #" << i; 853 << (*outputs)[i].touch_device_id << " to output #" << i;
639 break; 854 break;
640 } 855 }
641 } 856 }
642 } 857 }
643 858
644 XIFreeDeviceInfo(info); 859 XIFreeDeviceInfo(info);
645 } 860 }
646 861
647 } // namespace chromeos 862 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698