| Index: chromeos/display/real_output_configurator_delegate.cc
|
| diff --git a/chromeos/display/real_output_configurator_delegate.cc b/chromeos/display/real_output_configurator_delegate.cc
|
| index 6d0c78254112c5e678f0149aefc181cb6ebd448e..3313f0349e8eb7ba95e8a409614682f57b8255cb 100644
|
| --- a/chromeos/display/real_output_configurator_delegate.cc
|
| +++ b/chromeos/display/real_output_configurator_delegate.cc
|
| @@ -30,6 +30,12 @@ const float kMmInInch = 25.4;
|
| const float kDpi96 = 96.0;
|
| const float kPixelsToMmScale = kMmInInch / kDpi96;
|
|
|
| +// Prefixes of putput name
|
| +const char kOutputPortName_VGA[] = "VGA";
|
| +const char kOutputPortName_HDMI[] = "HDMI";
|
| +const char kOutputPortName_DVI[] = "DVI";
|
| +const char kOutputPortName_DisplayPort[] = "DP";
|
| +
|
| bool IsInternalOutput(const XRROutputInfo* output_info) {
|
| return IsInternalOutputName(std::string(output_info->name));
|
| }
|
| @@ -370,6 +376,212 @@ RealOutputConfiguratorDelegate::InitOutputSnapshot(
|
| return output;
|
| }
|
|
|
| +bool RealOutputConfiguratorDelegate::GetHDCPState(RROutput id,
|
| + HDCPState* state) {
|
| + CHECK(screen_) << "Server not grabbed";
|
| + unsigned char* values = NULL;
|
| + int actual_format;
|
| + unsigned long nitems;
|
| + unsigned long bytes_after;
|
| + Atom actual_type;
|
| + int success;
|
| + Atom prop = XInternAtom(display_, "Content Protection", False);
|
| +
|
| + bool ok = true;
|
| + success = XRRGetOutputProperty(display_, id, prop, 0, 100, False,
|
| + False, AnyPropertyType, &actual_type,
|
| + &actual_format, &nitems, &bytes_after,
|
| + &values);
|
| + if (actual_type == None) {
|
| + LOG(ERROR) << "Property 'Content Protection' does not exist";
|
| + ok = false;
|
| + } else if (success == Success && actual_type == XA_ATOM &&
|
| + actual_format == 32 && nitems == 1) {
|
| + Atom value = reinterpret_cast<Atom*>(values)[0];
|
| + if (value == XInternAtom(display_, "Undesired", False))
|
| + *state = HDCP_State_Undesired;
|
| + else if (value == XInternAtom(display_, "Desired", False))
|
| + *state = HDCP_State_Desired;
|
| + else if (value == XInternAtom(display_, "Enabled", False))
|
| + *state = HDCP_State_Enabled;
|
| + else {
|
| + LOG(ERROR) << "Unknown property value: " << value;
|
| + ok = false;
|
| + }
|
| + } else {
|
| + LOG(ERROR) << "XRRGetOutputProperty failed";
|
| + ok = false;
|
| + }
|
| + if (values)
|
| + XFree(values);
|
| +
|
| + VLOG(3) << "HDCP state: " << ok << "," << *state;
|
| + return ok;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::SetHDCPState(RROutput id,
|
| + HDCPState state) {
|
| + CHECK(screen_) << "Server not grabbed";
|
| + Atom name = XInternAtom(display_, "Content Protection", False);
|
| + unsigned long value;
|
| + switch (state) {
|
| + case HDCP_State_Undesired:
|
| + value = XInternAtom(display_, "Undesired", False);
|
| + break;
|
| + case HDCP_State_Desired:
|
| + value = XInternAtom(display_, "Desired", False);
|
| + break;
|
| + default:
|
| + DCHECK(0) << "Invalid HDCP state: " << state;
|
| + return false;
|
| + }
|
| + unsigned char *data = (unsigned char*)&value;
|
| + XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32,
|
| + PropModeReplace, data, 1);
|
| + return true;
|
| +}
|
| +
|
| +bool DetermineLinkType(const XRROutputInfo* output_info,
|
| + PP_OutputProtectionLinkType_Private* link_type) {
|
| + std::string name(output_info->name);
|
| + if (IsInternalOutput(output_info)) {
|
| + *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_INTERNAL;
|
| + } else if (name.find(kOutputPortName_VGA) == 0) {
|
| + *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_VGA;
|
| + } else if (name.find(kOutputPortName_HDMI) == 0) {
|
| + *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI;
|
| + } else if (name.find(kOutputPortName_DisplayPort) == 0) {
|
| + *link_type = PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT;
|
| + } else {
|
| + DCHECK(0) << "Unknown link type: " << name;
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::GetOutputLinkType(
|
| + std::vector<PP_OutputProtectionLinkType_Private>& link_type) {
|
| + CHECK(screen_) << "Server not grabbed";
|
| + bool result = true;
|
| + for (int i = 0; i < screen_->noutput; ++i) {
|
| + RROutput this_id = screen_->outputs[i];
|
| + XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, this_id);
|
| + if (output_info->connection != RR_Connected) {
|
| + XRRFreeOutputInfo(output_info);
|
| + link_type.push_back(PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_NONE);
|
| + continue;
|
| + }
|
| +
|
| + PP_OutputProtectionLinkType_Private type;
|
| + if (DetermineLinkType(output_info, &type))
|
| + link_type.push_back(type);
|
| + else
|
| + result = false;
|
| + XRRFreeOutputInfo(output_info);
|
| + }
|
| + return result;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::GetOutputLinkMask(uint32_t* link_mask) {
|
| + std::vector<PP_OutputProtectionLinkType_Private> link_type;
|
| + *link_mask = 0;
|
| + if (!GetOutputLinkType(link_type))
|
| + return false;
|
| +
|
| + for (std::vector<PP_OutputProtectionLinkType_Private>::const_iterator it =
|
| + link_type.begin(); it != link_type.end(); ++it) {
|
| + *link_mask |= *it;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::GetProtectionMethods(
|
| + uint32_t* protection_mask) {
|
| + CHECK(screen_) << "Server not grabbed";
|
| + std::vector<PP_OutputProtectionLinkType_Private> link_type;
|
| + if (!GetOutputLinkType(link_type))
|
| + return false;
|
| +
|
| + uint32_t enabled = 0;
|
| + uint32_t unfulfiled = 0;
|
| +
|
| + DCHECK(screen_->noutput == (int)link_type.size());
|
| + for (int i = 0; i < screen_->noutput; ++i) {
|
| + PP_OutputProtectionLinkType_Private type = link_type[i];
|
| + if (type & (PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI |
|
| + PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) {
|
| + HDCPState state;
|
| + RROutput this_id = screen_->outputs[i];
|
| + if (!GetHDCPState(this_id, &state))
|
| + return false;
|
| + if (state == HDCP_State_Enabled)
|
| + enabled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP;
|
| + else
|
| + unfulfiled |= PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP;
|
| + }
|
| + }
|
| + *protection_mask = enabled & ~unfulfiled;
|
| + return true;
|
| +}
|
| +
|
| +uint32_t RealOutputConfiguratorDelegate::GetCombinedProtectionRequest() {
|
| + uint32_t combined_requirement = 0;
|
| + for (ProtectionRequests::const_iterator it =
|
| + client_protection_request_.begin();
|
| + it != client_protection_request_.end();
|
| + ++it) {
|
| + combined_requirement |= it->second;
|
| + }
|
| + return combined_requirement;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::EnableOutputProtection(
|
| + chrome::PepperOutputProtectionHost* client, uint32_t desired_method_mask) {
|
| + if (desired_method_mask == PP_OUTPUT_PROTECTION_METHOD_PRIVATE_NONE)
|
| + client_protection_request_.erase(client);
|
| + else
|
| + client_protection_request_[client] = desired_method_mask;
|
| +
|
| + uint32_t all_desires = GetCombinedProtectionRequest();
|
| + std::vector<PP_OutputProtectionLinkType_Private> link_type;
|
| + if (!GetOutputLinkType(link_type))
|
| + return false;
|
| + bool ok = true;
|
| + for (int i = 0; i < screen_->noutput; ++i) {
|
| + RROutput this_id = screen_->outputs[i];
|
| + PP_OutputProtectionLinkType_Private type = link_type[i];
|
| + if (type & (PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_HDMI |
|
| + PP_OUTPUT_PROTECTION_LINK_TYPE_PRIVATE_DISPLAYPORT)) {
|
| + if (all_desires & PP_OUTPUT_PROTECTION_METHOD_PRIVATE_HDCP) {
|
| + ok = SetHDCPState(this_id, HDCP_State_Desired);
|
| + } else {
|
| + ok = SetHDCPState(this_id, HDCP_State_Undesired);
|
| + }
|
| + }
|
| +
|
| + if (!ok)
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool RealOutputConfiguratorDelegate::QueryOutputProtectionStatus(
|
| + chrome::PepperOutputProtectionHost* client,
|
| + uint32_t* link_mask,
|
| + uint32_t* protection_mask) {
|
| + bool ok = GetProtectionMethods(protection_mask) &&
|
| + GetOutputLinkMask(link_mask);
|
| + ProtectionRequests::iterator it = client_protection_request_.find(client);
|
| +
|
| + // Don't reveal protections requested by other clients.
|
| + if (it != client_protection_request_.end()) {
|
| + *protection_mask &= it->second;
|
| + } else {
|
| + *protection_mask = 0;
|
| + }
|
| + return ok;
|
| +}
|
| +
|
| void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
|
| const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
|
| CHECK(screen_) << "Server not grabbed";
|
|
|