| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "chromeos/display/native_display_delegate_x11.h" |  | 
| 6 |  | 
| 7 #include <X11/Xatom.h> |  | 
| 8 #include <X11/Xlib.h> |  | 
| 9 #include <X11/extensions/dpms.h> |  | 
| 10 #include <X11/extensions/Xrandr.h> |  | 
| 11 #include <X11/extensions/XInput2.h> |  | 
| 12 |  | 
| 13 #include <utility> |  | 
| 14 |  | 
| 15 #include "base/logging.h" |  | 
| 16 #include "base/message_loop/message_loop.h" |  | 
| 17 #include "base/message_loop/message_pump_x11.h" |  | 
| 18 #include "base/x11/edid_parser_x11.h" |  | 
| 19 #include "base/x11/x11_error_tracker.h" |  | 
| 20 #include "chromeos/display/native_display_event_dispatcher_x11.h" |  | 
| 21 #include "chromeos/display/native_display_observer.h" |  | 
| 22 #include "chromeos/display/output_util.h" |  | 
| 23 |  | 
| 24 namespace chromeos { |  | 
| 25 |  | 
| 26 namespace { |  | 
| 27 |  | 
| 28 // DPI measurements. |  | 
| 29 const float kMmInInch = 25.4; |  | 
| 30 const float kDpi96 = 96.0; |  | 
| 31 const float kPixelsToMmScale = kMmInInch / kDpi96; |  | 
| 32 |  | 
| 33 // Prefixes of output name |  | 
| 34 const char kOutputName_VGA[] = "VGA"; |  | 
| 35 const char kOutputName_HDMI[] = "HDMI"; |  | 
| 36 const char kOutputName_DVI[] = "DVI"; |  | 
| 37 const char kOutputName_DisplayPort[] = "DP"; |  | 
| 38 |  | 
| 39 const char kContentProtectionAtomName[] = "Content Protection"; |  | 
| 40 const char kProtectionUndesiredAtomName[] = "Undesired"; |  | 
| 41 const char kProtectionDesiredAtomName[] = "Desired"; |  | 
| 42 const char kProtectionEnabledAtomName[] = "Enabled"; |  | 
| 43 |  | 
| 44 bool IsInternalOutput(const XRROutputInfo* output_info) { |  | 
| 45   return IsInternalOutputName(std::string(output_info->name)); |  | 
| 46 } |  | 
| 47 |  | 
| 48 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { |  | 
| 49   return output_info->nmode > 0 ? output_info->modes[0] : None; |  | 
| 50 } |  | 
| 51 |  | 
| 52 }  // namespace |  | 
| 53 |  | 
| 54 //////////////////////////////////////////////////////////////////////////////// |  | 
| 55 // NativeDisplayDelegateX11::HelperDelegateX11 |  | 
| 56 |  | 
| 57 class NativeDisplayDelegateX11::HelperDelegateX11 |  | 
| 58     : public NativeDisplayDelegateX11::HelperDelegate { |  | 
| 59  public: |  | 
| 60   HelperDelegateX11(NativeDisplayDelegateX11* delegate) |  | 
| 61       : delegate_(delegate) {} |  | 
| 62   virtual ~HelperDelegateX11() {} |  | 
| 63 |  | 
| 64   // NativeDisplayDelegateX11::HelperDelegate overrides: |  | 
| 65   virtual void UpdateXRandRConfiguration( |  | 
| 66       const base::NativeEvent& event) OVERRIDE { |  | 
| 67     XRRUpdateConfiguration(event); |  | 
| 68   } |  | 
| 69   virtual const std::vector<OutputConfigurator::OutputSnapshot>& |  | 
| 70       GetCachedOutputs() const OVERRIDE { |  | 
| 71     return delegate_->cached_outputs_; |  | 
| 72   } |  | 
| 73   virtual void NotifyDisplayObservers() OVERRIDE { |  | 
| 74     FOR_EACH_OBSERVER(NativeDisplayObserver, |  | 
| 75                       delegate_->observers_, |  | 
| 76                       OnConfigurationChanged()); |  | 
| 77   } |  | 
| 78 |  | 
| 79  private: |  | 
| 80   NativeDisplayDelegateX11* delegate_; |  | 
| 81 |  | 
| 82   DISALLOW_COPY_AND_ASSIGN(HelperDelegateX11); |  | 
| 83 }; |  | 
| 84 |  | 
| 85 //////////////////////////////////////////////////////////////////////////////// |  | 
| 86 // NativeDisplayDelegateX11::MessagePumpObserverX11 |  | 
| 87 |  | 
| 88 class NativeDisplayDelegateX11::MessagePumpObserverX11 |  | 
| 89     : public base::MessagePumpObserver { |  | 
| 90  public: |  | 
| 91   MessagePumpObserverX11(HelperDelegate* delegate); |  | 
| 92   virtual ~MessagePumpObserverX11(); |  | 
| 93 |  | 
| 94   // base::MessagePumpObserver overrides: |  | 
| 95   virtual base::EventStatus WillProcessEvent( |  | 
| 96       const base::NativeEvent& event) OVERRIDE; |  | 
| 97   virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE; |  | 
| 98 |  | 
| 99  private: |  | 
| 100   HelperDelegate* delegate_;  // Not owned. |  | 
| 101 |  | 
| 102   DISALLOW_COPY_AND_ASSIGN(MessagePumpObserverX11); |  | 
| 103 }; |  | 
| 104 |  | 
| 105 NativeDisplayDelegateX11::MessagePumpObserverX11::MessagePumpObserverX11( |  | 
| 106     HelperDelegate* delegate) : delegate_(delegate) {} |  | 
| 107 |  | 
| 108 NativeDisplayDelegateX11::MessagePumpObserverX11::~MessagePumpObserverX11() {} |  | 
| 109 |  | 
| 110 base::EventStatus |  | 
| 111 NativeDisplayDelegateX11::MessagePumpObserverX11::WillProcessEvent( |  | 
| 112     const base::NativeEvent& event) { |  | 
| 113   // XI_HierarchyChanged events are special. There is no window associated with |  | 
| 114   // these events. So process them directly from here. |  | 
| 115   if (event->type == GenericEvent && |  | 
| 116       event->xgeneric.evtype == XI_HierarchyChanged) { |  | 
| 117     VLOG(1) << "Received XI_HierarchyChanged event"; |  | 
| 118     // Defer configuring outputs to not stall event processing. |  | 
| 119     // This also takes care of same event being received twice. |  | 
| 120     delegate_->NotifyDisplayObservers(); |  | 
| 121   } |  | 
| 122 |  | 
| 123   return base::EVENT_CONTINUE; |  | 
| 124 } |  | 
| 125 |  | 
| 126 void NativeDisplayDelegateX11::MessagePumpObserverX11::DidProcessEvent( |  | 
| 127     const base::NativeEvent& event) { |  | 
| 128 } |  | 
| 129 |  | 
| 130 //////////////////////////////////////////////////////////////////////////////// |  | 
| 131 // NativeDisplayDelegateX11 implementation: |  | 
| 132 |  | 
| 133 NativeDisplayDelegateX11::NativeDisplayDelegateX11() |  | 
| 134     : display_(base::MessagePumpX11::GetDefaultXDisplay()), |  | 
| 135       window_(DefaultRootWindow(display_)), |  | 
| 136       screen_(NULL) {} |  | 
| 137 |  | 
| 138 NativeDisplayDelegateX11::~NativeDisplayDelegateX11() { |  | 
| 139   base::MessagePumpX11::Current()->RemoveDispatcherForRootWindow( |  | 
| 140       message_pump_dispatcher_.get()); |  | 
| 141   base::MessagePumpX11::Current()->RemoveObserver(message_pump_observer_.get()); |  | 
| 142 } |  | 
| 143 |  | 
| 144 void NativeDisplayDelegateX11::Initialize() { |  | 
| 145   int error_base_ignored = 0; |  | 
| 146   int xrandr_event_base = 0; |  | 
| 147   XRRQueryExtension(display_, &xrandr_event_base, &error_base_ignored); |  | 
| 148 |  | 
| 149   helper_delegate_.reset(new HelperDelegateX11(this)); |  | 
| 150   message_pump_dispatcher_.reset(new NativeDisplayEventDispatcherX11( |  | 
| 151       helper_delegate_.get(), xrandr_event_base)); |  | 
| 152   message_pump_observer_.reset(new MessagePumpObserverX11( |  | 
| 153       helper_delegate_.get())); |  | 
| 154 |  | 
| 155   base::MessagePumpX11::Current()->AddDispatcherForRootWindow( |  | 
| 156       message_pump_dispatcher_.get()); |  | 
| 157   // We can't do this with a root window listener because XI_HierarchyChanged |  | 
| 158   // messages don't have a target window. |  | 
| 159   base::MessagePumpX11::Current()->AddObserver(message_pump_observer_.get()); |  | 
| 160 } |  | 
| 161 |  | 
| 162 void NativeDisplayDelegateX11::GrabServer() { |  | 
| 163   CHECK(!screen_) << "Server already grabbed"; |  | 
| 164   XGrabServer(display_); |  | 
| 165   screen_ = XRRGetScreenResources(display_, window_); |  | 
| 166   CHECK(screen_); |  | 
| 167 } |  | 
| 168 |  | 
| 169 void NativeDisplayDelegateX11::UngrabServer() { |  | 
| 170   CHECK(screen_) << "Server not grabbed"; |  | 
| 171   XRRFreeScreenResources(screen_); |  | 
| 172   screen_ = NULL; |  | 
| 173   XUngrabServer(display_); |  | 
| 174 } |  | 
| 175 |  | 
| 176 void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); } |  | 
| 177 |  | 
| 178 void NativeDisplayDelegateX11::SetBackgroundColor(uint32 color_argb) { |  | 
| 179   // Configuring CRTCs/Framebuffer clears the boot screen image.  Set the |  | 
| 180   // same background color while configuring the display to minimize the |  | 
| 181   // duration of black screen at boot time. The background is filled with |  | 
| 182   // black later in ash::DisplayManager.  crbug.com/171050. |  | 
| 183   XSetWindowAttributes swa = {0}; |  | 
| 184   XColor color; |  | 
| 185   Colormap colormap = DefaultColormap(display_, 0); |  | 
| 186   // XColor uses 16 bits per color. |  | 
| 187   color.red = (color_argb & 0x00FF0000) >> 8; |  | 
| 188   color.green = (color_argb & 0x0000FF00); |  | 
| 189   color.blue = (color_argb & 0x000000FF) << 8; |  | 
| 190   color.flags = DoRed | DoGreen | DoBlue; |  | 
| 191   XAllocColor(display_, colormap, &color); |  | 
| 192   swa.background_pixel = color.pixel; |  | 
| 193   XChangeWindowAttributes(display_, window_, CWBackPixel, &swa); |  | 
| 194   XFreeColors(display_, colormap, &color.pixel, 1, 0); |  | 
| 195 } |  | 
| 196 |  | 
| 197 void NativeDisplayDelegateX11::ForceDPMSOn() { |  | 
| 198   CHECK(DPMSEnable(display_)); |  | 
| 199   CHECK(DPMSForceLevel(display_, DPMSModeOn)); |  | 
| 200 } |  | 
| 201 |  | 
| 202 std::vector<OutputConfigurator::OutputSnapshot> |  | 
| 203 NativeDisplayDelegateX11::GetOutputs() { |  | 
| 204   CHECK(screen_) << "Server not grabbed"; |  | 
| 205 |  | 
| 206   cached_outputs_.clear(); |  | 
| 207   RRCrtc last_used_crtc = None; |  | 
| 208 |  | 
| 209   for (int i = 0; i < screen_->noutput && cached_outputs_.size() < 2; ++i) { |  | 
| 210     RROutput output_id = screen_->outputs[i]; |  | 
| 211     XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id); |  | 
| 212     if (output_info->connection == RR_Connected) { |  | 
| 213       OutputConfigurator::OutputSnapshot output = |  | 
| 214           InitOutputSnapshot(output_id, output_info, &last_used_crtc, i); |  | 
| 215       VLOG(2) << "Found display " << cached_outputs_.size() << ":" |  | 
| 216               << " output=" << output.output << " crtc=" << output.crtc |  | 
| 217               << " current_mode=" << output.current_mode; |  | 
| 218       cached_outputs_.push_back(output); |  | 
| 219     } |  | 
| 220     XRRFreeOutputInfo(output_info); |  | 
| 221   } |  | 
| 222 |  | 
| 223   return cached_outputs_; |  | 
| 224 } |  | 
| 225 |  | 
| 226 void NativeDisplayDelegateX11::AddMode( |  | 
| 227     const OutputConfigurator::OutputSnapshot& output, RRMode mode) { |  | 
| 228   CHECK(screen_) << "Server not grabbed"; |  | 
| 229   VLOG(1) << "AddOutputMode: output=" << output.output << " mode=" << mode; |  | 
| 230   XRRAddOutputMode(display_, output.output, mode); |  | 
| 231 } |  | 
| 232 |  | 
| 233 bool NativeDisplayDelegateX11::Configure( |  | 
| 234     const OutputConfigurator::OutputSnapshot& output, |  | 
| 235     RRMode mode, |  | 
| 236     int x, |  | 
| 237     int y) { |  | 
| 238   return ConfigureCrtc(output.crtc, mode, output.output, x, y); |  | 
| 239 } |  | 
| 240 |  | 
| 241 bool NativeDisplayDelegateX11::ConfigureCrtc( |  | 
| 242     RRCrtc crtc, |  | 
| 243     RRMode mode, |  | 
| 244     RROutput output, |  | 
| 245     int x, |  | 
| 246     int y) { |  | 
| 247   CHECK(screen_) << "Server not grabbed"; |  | 
| 248   VLOG(1) << "ConfigureCrtc: crtc=" << crtc << " mode=" << mode |  | 
| 249           << " output=" << output << " x=" << x << " y=" << y; |  | 
| 250   // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a |  | 
| 251   // Status, which is typically 0 for failure and 1 for success. In |  | 
| 252   // actuality it returns a RRCONFIGSTATUS, which uses 0 for success. |  | 
| 253   return XRRSetCrtcConfig(display_, |  | 
| 254                           screen_, |  | 
| 255                           crtc, |  | 
| 256                           CurrentTime, |  | 
| 257                           x, |  | 
| 258                           y, |  | 
| 259                           mode, |  | 
| 260                           RR_Rotate_0, |  | 
| 261                           (output && mode) ? &output : NULL, |  | 
| 262                           (output && mode) ? 1 : 0) == RRSetConfigSuccess; |  | 
| 263 } |  | 
| 264 |  | 
| 265 void NativeDisplayDelegateX11::CreateFrameBuffer( |  | 
| 266     int width, |  | 
| 267     int height, |  | 
| 268     const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { |  | 
| 269   CHECK(screen_) << "Server not grabbed"; |  | 
| 270   int current_width = DisplayWidth(display_, DefaultScreen(display_)); |  | 
| 271   int current_height = DisplayHeight(display_, DefaultScreen(display_)); |  | 
| 272   VLOG(1) << "CreateFrameBuffer: new=" << width << "x" << height |  | 
| 273           << " current=" << current_width << "x" << current_height; |  | 
| 274   if (width == current_width && height == current_height) |  | 
| 275     return; |  | 
| 276 |  | 
| 277   DestroyUnusedCrtcs(outputs); |  | 
| 278   int mm_width = width * kPixelsToMmScale; |  | 
| 279   int mm_height = height * kPixelsToMmScale; |  | 
| 280   XRRSetScreenSize(display_, window_, width, height, mm_width, mm_height); |  | 
| 281 } |  | 
| 282 |  | 
| 283 bool NativeDisplayDelegateX11::InitModeInfo( |  | 
| 284     RRMode mode, |  | 
| 285     OutputConfigurator::ModeInfo* mode_info) { |  | 
| 286   DCHECK(mode_info); |  | 
| 287   CHECK(screen_) << "Server not grabbed"; |  | 
| 288   // TODO: Determine if we need to organize modes in a way which provides |  | 
| 289   // better than O(n) lookup time.  In many call sites, for example, the |  | 
| 290   // "next" mode is typically what we are looking for so using this |  | 
| 291   // helper might be too expensive. |  | 
| 292   for (int i = 0; i < screen_->nmode; ++i) { |  | 
| 293     if (mode == screen_->modes[i].id) { |  | 
| 294       const XRRModeInfo& info = screen_->modes[i]; |  | 
| 295       mode_info->width = info.width; |  | 
| 296       mode_info->height = info.height; |  | 
| 297       mode_info->interlaced = info.modeFlags & RR_Interlace; |  | 
| 298       if (info.hTotal && info.vTotal) { |  | 
| 299         mode_info->refresh_rate = |  | 
| 300             static_cast<float>(info.dotClock) / |  | 
| 301             (static_cast<float>(info.hTotal) * static_cast<float>(info.vTotal)); |  | 
| 302       } else { |  | 
| 303         mode_info->refresh_rate = 0.0f; |  | 
| 304       } |  | 
| 305       return true; |  | 
| 306     } |  | 
| 307   } |  | 
| 308   return false; |  | 
| 309 } |  | 
| 310 |  | 
| 311 OutputConfigurator::OutputSnapshot NativeDisplayDelegateX11::InitOutputSnapshot( |  | 
| 312     RROutput id, |  | 
| 313     XRROutputInfo* info, |  | 
| 314     RRCrtc* last_used_crtc, |  | 
| 315     int index) { |  | 
| 316   OutputConfigurator::OutputSnapshot output; |  | 
| 317   output.output = id; |  | 
| 318   output.width_mm = info->mm_width; |  | 
| 319   output.height_mm = info->mm_height; |  | 
| 320   output.has_display_id = base::GetDisplayId(id, index, &output.display_id); |  | 
| 321   output.index = index; |  | 
| 322   bool is_internal = IsInternalOutput(info); |  | 
| 323 |  | 
| 324   // Use the index as a valid display ID even if the internal |  | 
| 325   // display doesn't have valid EDID because the index |  | 
| 326   // will never change. |  | 
| 327   if (!output.has_display_id && is_internal) |  | 
| 328     output.has_display_id = true; |  | 
| 329 |  | 
| 330   if (info->crtc) { |  | 
| 331     XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc); |  | 
| 332     output.current_mode = crtc_info->mode; |  | 
| 333     output.x = crtc_info->x; |  | 
| 334     output.y = crtc_info->y; |  | 
| 335     XRRFreeCrtcInfo(crtc_info); |  | 
| 336   } |  | 
| 337 |  | 
| 338   // Assign a CRTC that isn't already in use. |  | 
| 339   for (int i = 0; i < info->ncrtc; ++i) { |  | 
| 340     if (info->crtcs[i] != *last_used_crtc) { |  | 
| 341       output.crtc = info->crtcs[i]; |  | 
| 342       *last_used_crtc = output.crtc; |  | 
| 343       break; |  | 
| 344     } |  | 
| 345   } |  | 
| 346 |  | 
| 347   output.native_mode = GetOutputNativeMode(info); |  | 
| 348   output.is_aspect_preserving_scaling = IsOutputAspectPreservingScaling(id); |  | 
| 349   output.touch_device_id = None; |  | 
| 350 |  | 
| 351   for (int i = 0; i < info->nmode; ++i) { |  | 
| 352     const RRMode mode = info->modes[i]; |  | 
| 353     OutputConfigurator::ModeInfo mode_info; |  | 
| 354     if (InitModeInfo(mode, &mode_info)) |  | 
| 355       output.mode_infos.insert(std::make_pair(mode, mode_info)); |  | 
| 356     else |  | 
| 357       LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; |  | 
| 358   } |  | 
| 359 |  | 
| 360   std::string name(info->name); |  | 
| 361   if (is_internal) { |  | 
| 362     output.type = ui::OUTPUT_TYPE_INTERNAL; |  | 
| 363   } else if (name.find(kOutputName_VGA) == 0) { |  | 
| 364     output.type = ui::OUTPUT_TYPE_VGA; |  | 
| 365   } else if (name.find(kOutputName_HDMI) == 0) { |  | 
| 366     output.type = ui::OUTPUT_TYPE_HDMI; |  | 
| 367   } else if (name.find(kOutputName_DVI) == 0) { |  | 
| 368     output.type = ui::OUTPUT_TYPE_DVI; |  | 
| 369   } else if (name.find(kOutputName_DisplayPort) == 0) { |  | 
| 370     output.type = ui::OUTPUT_TYPE_DISPLAYPORT; |  | 
| 371   } else { |  | 
| 372     LOG(ERROR) << "Unknown link type: " << name; |  | 
| 373     output.type = ui::OUTPUT_TYPE_UNKNOWN; |  | 
| 374   } |  | 
| 375 |  | 
| 376   return output; |  | 
| 377 } |  | 
| 378 |  | 
| 379 bool NativeDisplayDelegateX11::GetHDCPState( |  | 
| 380     const OutputConfigurator::OutputSnapshot& output, ui::HDCPState* state) { |  | 
| 381   unsigned char* values = NULL; |  | 
| 382   int actual_format = 0; |  | 
| 383   unsigned long nitems = 0; |  | 
| 384   unsigned long bytes_after = 0; |  | 
| 385   Atom actual_type = None; |  | 
| 386   int success = 0; |  | 
| 387   // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom. |  | 
| 388   Atom prop = XInternAtom(display_, kContentProtectionAtomName, False); |  | 
| 389 |  | 
| 390   bool ok = true; |  | 
| 391   // TODO(kcwu): Move this to x11_util (similar method calls in this file and |  | 
| 392   // output_util.cc) |  | 
| 393   success = XRRGetOutputProperty(display_, |  | 
| 394                                  output.output, |  | 
| 395                                  prop, |  | 
| 396                                  0, |  | 
| 397                                  100, |  | 
| 398                                  False, |  | 
| 399                                  False, |  | 
| 400                                  AnyPropertyType, |  | 
| 401                                  &actual_type, |  | 
| 402                                  &actual_format, |  | 
| 403                                  &nitems, |  | 
| 404                                  &bytes_after, |  | 
| 405                                  &values); |  | 
| 406   if (actual_type == None) { |  | 
| 407     LOG(ERROR) << "Property '" << kContentProtectionAtomName |  | 
| 408                << "' does not exist"; |  | 
| 409     ok = false; |  | 
| 410   } else if (success == Success && actual_type == XA_ATOM && |  | 
| 411              actual_format == 32 && nitems == 1) { |  | 
| 412     Atom value = reinterpret_cast<Atom*>(values)[0]; |  | 
| 413     if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) { |  | 
| 414       *state = ui::HDCP_STATE_UNDESIRED; |  | 
| 415     } else if (value == |  | 
| 416                XInternAtom(display_, kProtectionDesiredAtomName, False)) { |  | 
| 417       *state = ui::HDCP_STATE_DESIRED; |  | 
| 418     } else if (value == |  | 
| 419                XInternAtom(display_, kProtectionEnabledAtomName, False)) { |  | 
| 420       *state = ui::HDCP_STATE_ENABLED; |  | 
| 421     } else { |  | 
| 422       LOG(ERROR) << "Unknown " << kContentProtectionAtomName |  | 
| 423                  << " value: " << value; |  | 
| 424       ok = false; |  | 
| 425     } |  | 
| 426   } else { |  | 
| 427     LOG(ERROR) << "XRRGetOutputProperty failed"; |  | 
| 428     ok = false; |  | 
| 429   } |  | 
| 430   if (values) |  | 
| 431     XFree(values); |  | 
| 432 |  | 
| 433   VLOG(3) << "HDCP state: " << ok << "," << *state; |  | 
| 434   return ok; |  | 
| 435 } |  | 
| 436 |  | 
| 437 bool NativeDisplayDelegateX11::SetHDCPState( |  | 
| 438     const OutputConfigurator::OutputSnapshot& output, ui::HDCPState state) { |  | 
| 439   Atom name = XInternAtom(display_, kContentProtectionAtomName, False); |  | 
| 440   Atom value = None; |  | 
| 441   switch (state) { |  | 
| 442     case ui::HDCP_STATE_UNDESIRED: |  | 
| 443       value = XInternAtom(display_, kProtectionUndesiredAtomName, False); |  | 
| 444       break; |  | 
| 445     case ui::HDCP_STATE_DESIRED: |  | 
| 446       value = XInternAtom(display_, kProtectionDesiredAtomName, False); |  | 
| 447       break; |  | 
| 448     default: |  | 
| 449       NOTREACHED() << "Invalid HDCP state: " << state; |  | 
| 450       return false; |  | 
| 451   } |  | 
| 452   base::X11ErrorTracker err_tracker; |  | 
| 453   unsigned char* data = reinterpret_cast<unsigned char*>(&value); |  | 
| 454   XRRChangeOutputProperty( |  | 
| 455       display_, output.output, name, XA_ATOM, 32, PropModeReplace, data, 1); |  | 
| 456   if (err_tracker.FoundNewError()) { |  | 
| 457     LOG(ERROR) << "XRRChangeOutputProperty failed"; |  | 
| 458     return false; |  | 
| 459   } else { |  | 
| 460     return true; |  | 
| 461   } |  | 
| 462 } |  | 
| 463 |  | 
| 464 void NativeDisplayDelegateX11::DestroyUnusedCrtcs( |  | 
| 465     const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { |  | 
| 466   CHECK(screen_) << "Server not grabbed"; |  | 
| 467   // Setting the screen size will fail if any CRTC doesn't fit afterwards. |  | 
| 468   // At the same time, turning CRTCs off and back on uses up a lot of time. |  | 
| 469   // This function tries to be smart to avoid too many off/on cycles: |  | 
| 470   // - We disable all the CRTCs we won't need after the FB resize. |  | 
| 471   // - We set the new modes on CRTCs, if they fit in both the old and new |  | 
| 472   //   FBs, and park them at (0,0) |  | 
| 473   // - We disable the CRTCs we will need but don't fit in the old FB. Those |  | 
| 474   //   will be reenabled after the resize. |  | 
| 475   // We don't worry about the cached state of the outputs here since we are |  | 
| 476   // not interested in the state we are setting - we just try to get the CRTCs |  | 
| 477   // out of the way so we can rebuild the frame buffer. |  | 
| 478   for (int i = 0; i < screen_->ncrtc; ++i) { |  | 
| 479     // Default config is to disable the crtcs. |  | 
| 480     RRCrtc crtc = screen_->crtcs[i]; |  | 
| 481     RRMode mode = None; |  | 
| 482     RROutput output = None; |  | 
| 483     const OutputConfigurator::ModeInfo* mode_info = NULL; |  | 
| 484     for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it = |  | 
| 485              outputs.begin(); |  | 
| 486          it != outputs.end(); |  | 
| 487          ++it) { |  | 
| 488       if (crtc == it->crtc) { |  | 
| 489         mode = it->current_mode; |  | 
| 490         output = it->output; |  | 
| 491         if (mode != None) |  | 
| 492           mode_info = OutputConfigurator::GetModeInfo(*it, mode); |  | 
| 493         break; |  | 
| 494       } |  | 
| 495     } |  | 
| 496 |  | 
| 497     if (mode_info) { |  | 
| 498       // In case our CRTC doesn't fit in our current framebuffer, disable it. |  | 
| 499       // It'll get reenabled after we resize the framebuffer. |  | 
| 500       int current_width = DisplayWidth(display_, DefaultScreen(display_)); |  | 
| 501       int current_height = DisplayHeight(display_, DefaultScreen(display_)); |  | 
| 502       if (mode_info->width > current_width || |  | 
| 503           mode_info->height > current_height) { |  | 
| 504         mode = None; |  | 
| 505         output = None; |  | 
| 506         mode_info = NULL; |  | 
| 507       } |  | 
| 508     } |  | 
| 509 |  | 
| 510     ConfigureCrtc(crtc, mode, output, 0, 0); |  | 
| 511   } |  | 
| 512 } |  | 
| 513 |  | 
| 514 bool NativeDisplayDelegateX11::IsOutputAspectPreservingScaling(RROutput id) { |  | 
| 515   bool ret = false; |  | 
| 516 |  | 
| 517   Atom scaling_prop = XInternAtom(display_, "scaling mode", False); |  | 
| 518   Atom full_aspect_atom = XInternAtom(display_, "Full aspect", False); |  | 
| 519   if (scaling_prop == None || full_aspect_atom == None) |  | 
| 520     return false; |  | 
| 521 |  | 
| 522   int nprop = 0; |  | 
| 523   Atom* props = XRRListOutputProperties(display_, id, &nprop); |  | 
| 524   for (int j = 0; j < nprop && !ret; j++) { |  | 
| 525     Atom prop = props[j]; |  | 
| 526     if (scaling_prop == prop) { |  | 
| 527       unsigned char* values = NULL; |  | 
| 528       int actual_format; |  | 
| 529       unsigned long nitems; |  | 
| 530       unsigned long bytes_after; |  | 
| 531       Atom actual_type; |  | 
| 532       int success; |  | 
| 533 |  | 
| 534       success = XRRGetOutputProperty(display_, |  | 
| 535                                      id, |  | 
| 536                                      prop, |  | 
| 537                                      0, |  | 
| 538                                      100, |  | 
| 539                                      False, |  | 
| 540                                      False, |  | 
| 541                                      AnyPropertyType, |  | 
| 542                                      &actual_type, |  | 
| 543                                      &actual_format, |  | 
| 544                                      &nitems, |  | 
| 545                                      &bytes_after, |  | 
| 546                                      &values); |  | 
| 547       if (success == Success && actual_type == XA_ATOM && actual_format == 32 && |  | 
| 548           nitems == 1) { |  | 
| 549         Atom value = reinterpret_cast<Atom*>(values)[0]; |  | 
| 550         if (full_aspect_atom == value) |  | 
| 551           ret = true; |  | 
| 552       } |  | 
| 553       if (values) |  | 
| 554         XFree(values); |  | 
| 555     } |  | 
| 556   } |  | 
| 557   if (props) |  | 
| 558     XFree(props); |  | 
| 559 |  | 
| 560   return ret; |  | 
| 561 } |  | 
| 562 |  | 
| 563 void NativeDisplayDelegateX11::AddObserver(NativeDisplayObserver* observer) { |  | 
| 564   observers_.AddObserver(observer); |  | 
| 565 } |  | 
| 566 |  | 
| 567 void NativeDisplayDelegateX11::RemoveObserver(NativeDisplayObserver* observer) { |  | 
| 568   observers_.RemoveObserver(observer); |  | 
| 569 } |  | 
| 570 |  | 
| 571 }  // namespace chromeos |  | 
| OLD | NEW | 
|---|