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

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: revise output configurator related code. rebased. 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>
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 "chromeos/dbus/dbus_thread_manager.h" 20 #include "chromeos/dbus/dbus_thread_manager.h"
21 #include "chromeos/dbus/power_manager_client.h" 21 #include "chromeos/dbus/power_manager_client.h"
22 #include "chromeos/display/output_util.h" 22 #include "chromeos/display/output_util.h"
23 #include "ui/base/x/x11_error_tracker.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
33 bool IsInternalOutput(const XRROutputInfo* output_info) { 40 bool IsInternalOutput(const XRROutputInfo* output_info) {
34 return IsInternalOutputName(std::string(output_info->name)); 41 return IsInternalOutputName(std::string(output_info->name));
35 } 42 }
36 43
37 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { 44 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) {
38 return output_info->nmode > 0 ? output_info->modes[0] : None; 45 return output_info->nmode > 0 ? output_info->modes[0] : None;
39 } 46 }
40 47
41 } // namespace 48 } // namespace
42 49
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 OutputConfigurator::ModeInfo mode_info; 306 OutputConfigurator::ModeInfo mode_info;
300 if (InitModeInfo(mode, &mode_info)) 307 if (InitModeInfo(mode, &mode_info))
301 output.mode_infos.insert(std::make_pair(mode, mode_info)); 308 output.mode_infos.insert(std::make_pair(mode, mode_info));
302 else 309 else
303 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; 310 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
304 } 311 }
305 312
306 return output; 313 return output;
307 } 314 }
308 315
316 bool RealOutputConfiguratorDelegate::GetHDCPState(RROutput id,
317 HDCPState* state) {
318 CHECK(screen_) << "Server not grabbed";
319 unsigned char* values = NULL;
320 int actual_format = 0;
321 unsigned long nitems = 0;
322 unsigned long bytes_after = 0;
323 Atom actual_type = None;
324 int success = 0;
325 Atom prop = XInternAtom(display_, "Content Protection", False);
Daniel Erat 2013/09/20 15:00:24 please move this to a constant at the top of the f
kcwu 2013/09/20 20:29:30 Done.
326
327 bool ok = true;
328 // TODO(kcwu): Move this to x11_util (similar method calls in this file and
329 // output_util.cc)
330 success = XRRGetOutputProperty(display_, id, prop, 0, 100, False,
331 False, AnyPropertyType, &actual_type,
332 &actual_format, &nitems, &bytes_after,
333 &values);
334 if (actual_type == None) {
335 LOG(ERROR) << "Property 'Content Protection' does not exist";
336 ok = false;
337 } else if (success == Success && actual_type == XA_ATOM &&
338 actual_format == 32 && nitems == 1) {
339 Atom value = reinterpret_cast<Atom*>(values)[0];
340 if (value == XInternAtom(display_, "Undesired", False)) {
Daniel Erat 2013/09/20 15:00:24 please make constants for these too so they aren't
kcwu 2013/09/20 20:29:30 Done.
341 *state = HDCP_STATE_UNDESIRED;
342 } else if (value == XInternAtom(display_, "Desired", False)) {
343 *state = HDCP_STATE_DESIRED;
344 } else if (value == XInternAtom(display_, "Enabled", False)) {
345 *state = HDCP_STATE_ENABLED;
346 } else {
347 LOG(ERROR) << "Unknown property value: " << value;
Daniel Erat 2013/09/20 15:00:24 nit: mind changing this to "Unknown " << kContentP
kcwu 2013/09/20 20:29:30 Done.
348 ok = false;
349 }
350 } else {
351 LOG(ERROR) << "XRRGetOutputProperty failed";
352 ok = false;
353 }
354 if (values)
355 XFree(values);
356
357 VLOG(3) << "HDCP state: " << ok << "," << *state;
358 return ok;
359 }
360
361 bool RealOutputConfiguratorDelegate::SetHDCPState(RROutput id,
362 HDCPState state) {
363 CHECK(screen_) << "Server not grabbed";
364 Atom name = XInternAtom(display_, "Content Protection", False);
365 Atom value;
366 switch (state) {
367 case HDCP_STATE_UNDESIRED:
368 value = XInternAtom(display_, "Undesired", False);
369 break;
370 case HDCP_STATE_DESIRED:
371 value = XInternAtom(display_, "Desired", False);
372 break;
373 default:
374 NOTREACHED() << "Invalid HDCP state: " << state;
375 return false;
376 }
377 ui::X11ErrorTracker err_tracker;
378 unsigned char *data = reinterpret_cast<unsigned char*>(&value);
379 XRRChangeOutputProperty(display_, id, name, XA_ATOM, 32,
380 PropModeReplace, data, 1);
381 if (err_tracker.FoundNewError()) {
382 LOG(ERROR) << "XRRChangeOutputProperty failed";
383 return false;
384 } else {
385 return true;
386 }
387 }
388
389 bool RealOutputConfiguratorDelegate::QueryOutputProtectionLinkType(
390 RROutput id,
391 OutputType *link_type) {
392 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, id);
393 if (!output_info) {
394 return false;
395 }
396
397 bool ok = true;
398 if (output_info->connection == RR_Connected) {
399 std::string name(output_info->name);
400 if (IsInternalOutput(output_info)) {
401 *link_type = OUTPUT_TYPE_INTERNAL;
402 } else if (name.find(kOutputName_VGA) == 0) {
403 *link_type = OUTPUT_TYPE_VGA;
404 } else if (name.find(kOutputName_HDMI) == 0) {
405 *link_type = OUTPUT_TYPE_HDMI;
406 } else if (name.find(kOutputName_DVI) == 0) {
407 *link_type = OUTPUT_TYPE_DVI;
408 } else if (name.find(kOutputName_DisplayPort) == 0) {
409 *link_type = OUTPUT_TYPE_DISPLAYPORT;
410 } else {
411 DCHECK(0) << "Unknown link type: " << name;
Daniel Erat 2013/09/20 15:00:24 use NOTREACHED() or maybe just LOG(ERROR) instead
kcwu 2013/09/20 20:29:30 Done.
412 ok = false;
413 }
414 } else {
415 *link_type = OUTPUT_TYPE_NONE;
416 }
417 XRRFreeOutputInfo(output_info);
418 return ok;
419 }
420
421 bool RealOutputConfiguratorDelegate::EnableOutputProtection(
422 chromeos::OutputConfigurator::OutputProtectionClientId client_id,
423 uint32_t desired_method_mask) {
424 if (desired_method_mask == OUTPUT_PROTECTION_METHOD_NONE)
425 client_protection_requests_.erase(client_id);
426 else
427 client_protection_requests_[client_id] = desired_method_mask;
Daniel Erat 2013/09/20 15:00:24 should you hold off on updating the request map un
kcwu 2013/09/20 20:29:30 Done.
428
429 uint32_t all_desires = 0;
430 for (ProtectionRequests::const_iterator it =
431 client_protection_requests_.begin();
432 it != client_protection_requests_.end();
433 ++it) {
434 all_desires |= it->second;
435 }
436
437 for (int i = 0; i < screen_->noutput; ++i) {
438 RROutput this_id = screen_->outputs[i];
439 OutputType type;
440 if (!QueryOutputProtectionLinkType(this_id, &type))
441 return false;
442
443 if ((type & OUTPUT_TYPE_HDMI) ||
444 (type & OUTPUT_TYPE_DISPLAYPORT)) {
445 HDCPState new_desired_state;
Daniel Erat 2013/09/20 15:00:24 nit: HDCPState new_desired_state = (all_d
kcwu 2013/09/20 20:29:30 Done.
446 if (all_desires & OUTPUT_PROTECTION_METHOD_HDCP) {
447 new_desired_state = HDCP_STATE_DESIRED;
448 } else {
449 new_desired_state = HDCP_STATE_UNDESIRED;
450 }
451 if (!SetHDCPState(this_id, new_desired_state))
452 return false;
453 }
454 }
455 return true;
456 }
457
458 bool RealOutputConfiguratorDelegate::QueryOutputProtectionStatus(
459 chromeos::OutputConfigurator::OutputProtectionClientId client_id,
460 uint32_t* link_mask,
461 uint32_t* protection_mask) {
Daniel Erat 2013/09/20 15:00:24 mind adding a CHECK(screen_) here too? but this s
Daniel Erat 2013/09/20 15:08:26 moreover, is there any reason why you can't save t
kcwu 2013/09/20 20:29:30 I'm confused. marcheu said grabbing is not strictl
kcwu 2013/09/20 20:29:30 Ah, I didn't notice OutputSnapshot was added recen
Daniel Erat 2013/09/20 20:40:59 screen_ is only valid while the server is grabbed
kcwu 2013/09/23 18:00:02 Done.
462 uint32_t enabled = 0;
463 uint32_t unfulfilled = 0;
464
465 *link_mask = 0;
466 for (int i = 0; i < screen_->noutput; ++i) {
467 RROutput this_id = screen_->outputs[i];
468 OutputType type;
469 if (!QueryOutputProtectionLinkType(this_id, &type))
470 return false;
471 *link_mask |= type;
472
473 if ((type & OUTPUT_TYPE_HDMI) ||
474 (type & OUTPUT_TYPE_DISPLAYPORT)) {
475 HDCPState state;
476 RROutput this_id = screen_->outputs[i];
Daniel Erat 2013/09/20 15:00:24 i think you're shadowing the earlier |this_id| var
kcwu 2013/09/20 20:29:30 Done.
477 if (!GetHDCPState(this_id, &state))
478 return false;
479 if (state == HDCP_STATE_ENABLED)
480 enabled |= OUTPUT_PROTECTION_METHOD_HDCP;
481 else
482 unfulfilled |= OUTPUT_PROTECTION_METHOD_HDCP;
483 }
484 }
485
486 // Don't reveal protections requested by other clients.
487 ProtectionRequests::iterator it = client_protection_requests_.find(client_id);
488 if (it != client_protection_requests_.end()) {
489 uint32_t requested_mask = it->second;
490 *protection_mask = enabled & ~unfulfilled & requested_mask;
491 } else {
492 *protection_mask = 0;
493 }
494 return true;
495 }
496
309 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( 497 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
310 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { 498 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
311 CHECK(screen_) << "Server not grabbed"; 499 CHECK(screen_) << "Server not grabbed";
312 // Setting the screen size will fail if any CRTC doesn't fit afterwards. 500 // 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. 501 // 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: 502 // 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. 503 // - 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 504 // - We set the new modes on CRTCs, if they fit in both the old and new
317 // FBs, and park them at (0,0) 505 // FBs, and park them at (0,0)
318 // - We disable the CRTCs we will need but don't fit in the old FB. Those 506 // - 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
500 << (*outputs)[i].touch_device_id << " to output #" << i; 688 << (*outputs)[i].touch_device_id << " to output #" << i;
501 break; 689 break;
502 } 690 }
503 } 691 }
504 } 692 }
505 693
506 XIFreeDeviceInfo(info); 694 XIFreeDeviceInfo(info);
507 } 695 }
508 696
509 } // namespace chromeos 697 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698