| 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 "ui/display/chromeos/x11/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/macros.h" |  | 
|   17 #include "base/memory/ptr_util.h" |  | 
|   18 #include "ui/display/chromeos/x11/display_mode_x11.h" |  | 
|   19 #include "ui/display/chromeos/x11/display_snapshot_x11.h" |  | 
|   20 #include "ui/display/chromeos/x11/display_util_x11.h" |  | 
|   21 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h" |  | 
|   22 #include "ui/display/types/native_display_observer.h" |  | 
|   23 #include "ui/display/util/x11/edid_parser_x11.h" |  | 
|   24 #include "ui/events/platform/platform_event_source.h" |  | 
|   25 #include "ui/gfx/geometry/rect.h" |  | 
|   26 #include "ui/gfx/x/x11_error_tracker.h" |  | 
|   27 #include "ui/gfx/x/x11_types.h" |  | 
|   28  |  | 
|   29 namespace ui { |  | 
|   30  |  | 
|   31 namespace { |  | 
|   32  |  | 
|   33 // DPI measurements. |  | 
|   34 const float kMmInInch = 25.4; |  | 
|   35 const float kDpi96 = 96.0; |  | 
|   36 const float kPixelsToMmScale = kMmInInch / kDpi96; |  | 
|   37  |  | 
|   38 const char kContentProtectionAtomName[] = "Content Protection"; |  | 
|   39 const char kProtectionUndesiredAtomName[] = "Undesired"; |  | 
|   40 const char kProtectionDesiredAtomName[] = "Desired"; |  | 
|   41 const char kProtectionEnabledAtomName[] = "Enabled"; |  | 
|   42  |  | 
|   43 RRMode GetOutputNativeMode(const XRROutputInfo* output_info) { |  | 
|   44   return output_info->nmode > 0 ? output_info->modes[0] : None; |  | 
|   45 } |  | 
|   46  |  | 
|   47 XRRCrtcGamma* ResampleGammaRamp(XRRCrtcGamma* gamma_ramp, int gamma_ramp_size) { |  | 
|   48   if (gamma_ramp->size == gamma_ramp_size) |  | 
|   49     return gamma_ramp; |  | 
|   50  |  | 
|   51 #define RESAMPLE(array, i, r) \ |  | 
|   52   array[i] + (array[i + 1] - array[i]) * r / gamma_ramp_size |  | 
|   53  |  | 
|   54   XRRCrtcGamma* resampled = XRRAllocGamma(gamma_ramp_size); |  | 
|   55   for (int i = 0; i < gamma_ramp_size; ++i) { |  | 
|   56     int base_index = gamma_ramp->size * i / gamma_ramp_size; |  | 
|   57     int remaining = gamma_ramp->size * i % gamma_ramp_size; |  | 
|   58     if (base_index < gamma_ramp->size - 1) { |  | 
|   59       resampled->red[i] = RESAMPLE(gamma_ramp->red, base_index, remaining); |  | 
|   60       resampled->green[i] = RESAMPLE(gamma_ramp->green, base_index, remaining); |  | 
|   61       resampled->blue[i] = RESAMPLE(gamma_ramp->blue, base_index, remaining); |  | 
|   62     } else { |  | 
|   63       resampled->red[i] = gamma_ramp->red[gamma_ramp->size - 1]; |  | 
|   64       resampled->green[i] = gamma_ramp->green[gamma_ramp->size - 1]; |  | 
|   65       resampled->blue[i] = gamma_ramp->blue[gamma_ramp->size - 1]; |  | 
|   66     } |  | 
|   67   } |  | 
|   68  |  | 
|   69 #undef RESAMPLE |  | 
|   70   XRRFreeGamma(gamma_ramp); |  | 
|   71   return resampled; |  | 
|   72 } |  | 
|   73  |  | 
|   74 }  // namespace |  | 
|   75  |  | 
|   76 //////////////////////////////////////////////////////////////////////////////// |  | 
|   77 // NativeDisplayDelegateX11::HelperDelegateX11 |  | 
|   78  |  | 
|   79 class NativeDisplayDelegateX11::HelperDelegateX11 |  | 
|   80     : public NativeDisplayDelegateX11::HelperDelegate { |  | 
|   81  public: |  | 
|   82   HelperDelegateX11(NativeDisplayDelegateX11* delegate) : delegate_(delegate) {} |  | 
|   83   ~HelperDelegateX11() override {} |  | 
|   84  |  | 
|   85   // NativeDisplayDelegateX11::HelperDelegate overrides: |  | 
|   86   void UpdateXRandRConfiguration(const base::NativeEvent& event) override { |  | 
|   87     XRRUpdateConfiguration(event); |  | 
|   88   } |  | 
|   89   const std::vector<DisplaySnapshot*>& GetCachedDisplays() const override { |  | 
|   90     return delegate_->cached_outputs_.get(); |  | 
|   91   } |  | 
|   92   void NotifyDisplayObservers() override { |  | 
|   93     for (NativeDisplayObserver& observer : delegate_->observers_) |  | 
|   94       observer.OnConfigurationChanged(); |  | 
|   95   } |  | 
|   96  |  | 
|   97  private: |  | 
|   98   NativeDisplayDelegateX11* delegate_; |  | 
|   99  |  | 
|  100   DISALLOW_COPY_AND_ASSIGN(HelperDelegateX11); |  | 
|  101 }; |  | 
|  102  |  | 
|  103 //////////////////////////////////////////////////////////////////////////////// |  | 
|  104 // NativeDisplayDelegateX11 implementation: |  | 
|  105  |  | 
|  106 NativeDisplayDelegateX11::NativeDisplayDelegateX11() |  | 
|  107     : display_(gfx::GetXDisplay()), |  | 
|  108       window_(DefaultRootWindow(display_)), |  | 
|  109       background_color_argb_(0) {} |  | 
|  110  |  | 
|  111 NativeDisplayDelegateX11::~NativeDisplayDelegateX11() { |  | 
|  112   if (ui::PlatformEventSource::GetInstance() && |  | 
|  113       platform_event_dispatcher_.get()) { |  | 
|  114     ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher( |  | 
|  115         platform_event_dispatcher_.get()); |  | 
|  116   } |  | 
|  117 } |  | 
|  118  |  | 
|  119 void NativeDisplayDelegateX11::Initialize() { |  | 
|  120   int error_base_ignored = 0; |  | 
|  121   int xrandr_event_base = 0; |  | 
|  122   XRRQueryExtension(display_, &xrandr_event_base, &error_base_ignored); |  | 
|  123  |  | 
|  124   helper_delegate_.reset(new HelperDelegateX11(this)); |  | 
|  125   platform_event_dispatcher_.reset(new NativeDisplayEventDispatcherX11( |  | 
|  126       helper_delegate_.get(), xrandr_event_base)); |  | 
|  127  |  | 
|  128   if (ui::PlatformEventSource::GetInstance()) { |  | 
|  129     ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher( |  | 
|  130         platform_event_dispatcher_.get()); |  | 
|  131   } |  | 
|  132 } |  | 
|  133  |  | 
|  134 void NativeDisplayDelegateX11::GrabServer() { |  | 
|  135   CHECK(!screen_) << "Server already grabbed"; |  | 
|  136   XGrabServer(display_); |  | 
|  137   screen_.reset(XRRGetScreenResources(display_, window_)); |  | 
|  138   CHECK(screen_); |  | 
|  139 } |  | 
|  140  |  | 
|  141 void NativeDisplayDelegateX11::UngrabServer() { |  | 
|  142   CHECK(screen_) << "Server not grabbed"; |  | 
|  143   screen_.reset(); |  | 
|  144   XUngrabServer(display_); |  | 
|  145   // crbug.com/366125 |  | 
|  146   XFlush(display_); |  | 
|  147 } |  | 
|  148  |  | 
|  149 void NativeDisplayDelegateX11::TakeDisplayControl( |  | 
|  150     const DisplayControlCallback& callback) { |  | 
|  151   NOTIMPLEMENTED(); |  | 
|  152 } |  | 
|  153  |  | 
|  154 void NativeDisplayDelegateX11::RelinquishDisplayControl( |  | 
|  155     const DisplayControlCallback& callback) { |  | 
|  156   NOTIMPLEMENTED(); |  | 
|  157 } |  | 
|  158  |  | 
|  159 void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); } |  | 
|  160  |  | 
|  161 void NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) { |  | 
|  162   background_color_argb_ = color_argb; |  | 
|  163 } |  | 
|  164  |  | 
|  165 void NativeDisplayDelegateX11::ForceDPMSOn() { |  | 
|  166   CHECK(DPMSEnable(display_)); |  | 
|  167   CHECK(DPMSForceLevel(display_, DPMSModeOn)); |  | 
|  168 } |  | 
|  169  |  | 
|  170 void NativeDisplayDelegateX11::GetDisplays( |  | 
|  171     const GetDisplaysCallback& callback) { |  | 
|  172   CHECK(screen_) << "Server not grabbed"; |  | 
|  173  |  | 
|  174   cached_outputs_.clear(); |  | 
|  175   std::set<RRCrtc> last_used_crtcs; |  | 
|  176  |  | 
|  177   InitModes(); |  | 
|  178   for (int i = 0; i < screen_->noutput; ++i) { |  | 
|  179     RROutput output_id = screen_->outputs[i]; |  | 
|  180     XRROutputInfo* output_info = |  | 
|  181         XRRGetOutputInfo(display_, screen_.get(), output_id); |  | 
|  182     if (output_info->connection == RR_Connected) { |  | 
|  183       DisplaySnapshotX11* output = |  | 
|  184           InitDisplaySnapshot(output_id, output_info, &last_used_crtcs, i); |  | 
|  185       cached_outputs_.push_back(output); |  | 
|  186     } |  | 
|  187     XRRFreeOutputInfo(output_info); |  | 
|  188   } |  | 
|  189  |  | 
|  190   callback.Run(cached_outputs_.get()); |  | 
|  191 } |  | 
|  192  |  | 
|  193 void NativeDisplayDelegateX11::AddMode(const DisplaySnapshot& output, |  | 
|  194                                        const DisplayMode* mode) { |  | 
|  195   CHECK(screen_) << "Server not grabbed"; |  | 
|  196   CHECK(mode) << "Must add valid mode"; |  | 
|  197  |  | 
|  198   const DisplaySnapshotX11& x11_output = |  | 
|  199       static_cast<const DisplaySnapshotX11&>(output); |  | 
|  200   RRMode mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id(); |  | 
|  201  |  | 
|  202   VLOG(1) << "AddDisplayMode: output=" << x11_output.output() |  | 
|  203           << " mode=" << mode_id; |  | 
|  204   XRRAddOutputMode(display_, x11_output.output(), mode_id); |  | 
|  205 } |  | 
|  206  |  | 
|  207 void NativeDisplayDelegateX11::Configure(const DisplaySnapshot& output, |  | 
|  208                                          const DisplayMode* mode, |  | 
|  209                                          const gfx::Point& origin, |  | 
|  210                                          const ConfigureCallback& callback) { |  | 
|  211   const DisplaySnapshotX11& x11_output = |  | 
|  212       static_cast<const DisplaySnapshotX11&>(output); |  | 
|  213   RRMode mode_id = None; |  | 
|  214   if (mode) |  | 
|  215     mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id(); |  | 
|  216  |  | 
|  217   callback.Run(ConfigureCrtc(x11_output.crtc(), mode_id, x11_output.output(), |  | 
|  218                              origin.x(), origin.y())); |  | 
|  219 } |  | 
|  220  |  | 
|  221 bool NativeDisplayDelegateX11::ConfigureCrtc(RRCrtc crtc, |  | 
|  222                                              RRMode mode, |  | 
|  223                                              RROutput output, |  | 
|  224                                              int x, |  | 
|  225                                              int y) { |  | 
|  226   CHECK(screen_) << "Server not grabbed"; |  | 
|  227   VLOG(1) << "ConfigureCrtc: crtc=" << crtc << " mode=" << mode |  | 
|  228           << " output=" << output << " x=" << x << " y=" << y; |  | 
|  229   // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a |  | 
|  230   // Status, which is typically 0 for failure and 1 for success. In |  | 
|  231   // actuality it returns a RRCONFIGSTATUS, which uses 0 for success. |  | 
|  232   if (XRRSetCrtcConfig(display_, screen_.get(), crtc, CurrentTime, x, y, mode, |  | 
|  233                        RR_Rotate_0, (output && mode) ? &output : NULL, |  | 
|  234                        (output && mode) ? 1 : 0) != RRSetConfigSuccess) { |  | 
|  235     LOG(WARNING) << "Unable to configure CRTC " << crtc << ":" |  | 
|  236                  << " mode=" << mode << " output=" << output << " x=" << x |  | 
|  237                  << " y=" << y; |  | 
|  238     return false; |  | 
|  239   } |  | 
|  240  |  | 
|  241   return true; |  | 
|  242 } |  | 
|  243  |  | 
|  244 void NativeDisplayDelegateX11::CreateFrameBuffer(const gfx::Size& size) { |  | 
|  245   CHECK(screen_) << "Server not grabbed"; |  | 
|  246   gfx::Size current_screen_size( |  | 
|  247       DisplayWidth(display_, DefaultScreen(display_)), |  | 
|  248       DisplayHeight(display_, DefaultScreen(display_))); |  | 
|  249  |  | 
|  250   VLOG(1) << "CreateFrameBuffer: new=" << size.ToString() |  | 
|  251           << " current=" << current_screen_size.ToString(); |  | 
|  252  |  | 
|  253   DestroyUnusedCrtcs(); |  | 
|  254  |  | 
|  255   if (size == current_screen_size) |  | 
|  256     return; |  | 
|  257  |  | 
|  258   gfx::Size min_screen_size(current_screen_size); |  | 
|  259   min_screen_size.SetToMin(size); |  | 
|  260   UpdateCrtcsForNewFramebuffer(min_screen_size); |  | 
|  261  |  | 
|  262   int mm_width = size.width() * kPixelsToMmScale; |  | 
|  263   int mm_height = size.height() * kPixelsToMmScale; |  | 
|  264   XRRSetScreenSize( |  | 
|  265       display_, window_, size.width(), size.height(), mm_width, mm_height); |  | 
|  266   // We don't wait for root window resize, therefore this end up with drawing |  | 
|  267   // in the old window size, which we care during the boot. |  | 
|  268   DrawBackground(); |  | 
|  269  |  | 
|  270   // Don't redraw the background upon framebuffer change again. This should |  | 
|  271   // happen only once after boot. |  | 
|  272   background_color_argb_ = 0; |  | 
|  273 } |  | 
|  274  |  | 
|  275 void NativeDisplayDelegateX11::AddObserver(NativeDisplayObserver* observer) { |  | 
|  276   observers_.AddObserver(observer); |  | 
|  277 } |  | 
|  278  |  | 
|  279 void NativeDisplayDelegateX11::RemoveObserver(NativeDisplayObserver* observer) { |  | 
|  280   observers_.RemoveObserver(observer); |  | 
|  281 } |  | 
|  282  |  | 
|  283 display::FakeDisplayController* |  | 
|  284 NativeDisplayDelegateX11::GetFakeDisplayController() { |  | 
|  285   return nullptr; |  | 
|  286 } |  | 
|  287  |  | 
|  288 void NativeDisplayDelegateX11::InitModes() { |  | 
|  289   CHECK(screen_) << "Server not grabbed"; |  | 
|  290  |  | 
|  291   modes_.clear(); |  | 
|  292  |  | 
|  293   for (int i = 0; i < screen_->nmode; ++i) { |  | 
|  294     const XRRModeInfo& info = screen_->modes[i]; |  | 
|  295     float refresh_rate = 0.0f; |  | 
|  296     if (info.hTotal && info.vTotal) { |  | 
|  297       refresh_rate = |  | 
|  298           static_cast<float>(info.dotClock) / |  | 
|  299           (static_cast<float>(info.hTotal) * static_cast<float>(info.vTotal)); |  | 
|  300     } |  | 
|  301  |  | 
|  302     modes_.insert(std::make_pair( |  | 
|  303         info.id, base::MakeUnique<DisplayModeX11>( |  | 
|  304                      gfx::Size(info.width, info.height), |  | 
|  305                      info.modeFlags & RR_Interlace, refresh_rate, info.id))); |  | 
|  306   } |  | 
|  307 } |  | 
|  308  |  | 
|  309 DisplaySnapshotX11* NativeDisplayDelegateX11::InitDisplaySnapshot( |  | 
|  310     RROutput output, |  | 
|  311     XRROutputInfo* info, |  | 
|  312     std::set<RRCrtc>* last_used_crtcs, |  | 
|  313     int index) { |  | 
|  314   int64_t display_id = 0; |  | 
|  315   display::EDIDParserX11 edid_parser(output); |  | 
|  316   if (!edid_parser.GetDisplayId(static_cast<uint8_t>(index), &display_id)) |  | 
|  317     display_id = index; |  | 
|  318  |  | 
|  319   bool has_overscan = false; |  | 
|  320   edid_parser.GetOutputOverscanFlag(&has_overscan); |  | 
|  321  |  | 
|  322   DisplayConnectionType type = GetDisplayConnectionTypeFromName(info->name); |  | 
|  323   if (type == DISPLAY_CONNECTION_TYPE_UNKNOWN) |  | 
|  324     LOG(ERROR) << "Unknown link type: " << info->name; |  | 
|  325  |  | 
|  326   RRMode native_mode_id = GetOutputNativeMode(info); |  | 
|  327   RRMode current_mode_id = None; |  | 
|  328   gfx::Point origin; |  | 
|  329   if (info->crtc) { |  | 
|  330     XRRCrtcInfo* crtc_info = |  | 
|  331         XRRGetCrtcInfo(display_, screen_.get(), info->crtc); |  | 
|  332     current_mode_id = crtc_info->mode; |  | 
|  333     origin.SetPoint(crtc_info->x, crtc_info->y); |  | 
|  334     XRRFreeCrtcInfo(crtc_info); |  | 
|  335   } |  | 
|  336  |  | 
|  337   RRCrtc crtc = None; |  | 
|  338   // Assign a CRTC that isn't already in use. |  | 
|  339   for (int i = 0; i < info->ncrtc; ++i) { |  | 
|  340     if (last_used_crtcs->find(info->crtcs[i]) == last_used_crtcs->end()) { |  | 
|  341       crtc = info->crtcs[i]; |  | 
|  342       last_used_crtcs->insert(crtc); |  | 
|  343       break; |  | 
|  344     } |  | 
|  345   } |  | 
|  346  |  | 
|  347   const DisplayMode* current_mode = NULL; |  | 
|  348   const DisplayMode* native_mode = NULL; |  | 
|  349   std::vector<std::unique_ptr<const DisplayMode>> display_modes; |  | 
|  350  |  | 
|  351   for (int i = 0; i < info->nmode; ++i) { |  | 
|  352     const RRMode mode = info->modes[i]; |  | 
|  353     if (modes_.find(mode) != modes_.end()) { |  | 
|  354       display_modes.push_back(modes_.at(mode)->Clone()); |  | 
|  355  |  | 
|  356       if (mode == current_mode_id) |  | 
|  357         current_mode = display_modes.back().get(); |  | 
|  358       if (mode == native_mode_id) |  | 
|  359         native_mode = display_modes.back().get(); |  | 
|  360     } else { |  | 
|  361       LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode; |  | 
|  362     } |  | 
|  363   } |  | 
|  364  |  | 
|  365   DisplaySnapshotX11* display_snapshot = |  | 
|  366       new DisplaySnapshotX11(display_id, |  | 
|  367                              origin, |  | 
|  368                              gfx::Size(info->mm_width, info->mm_height), |  | 
|  369                              type, |  | 
|  370                              IsOutputAspectPreservingScaling(output), |  | 
|  371                              has_overscan, |  | 
|  372                              edid_parser.GetDisplayName(), |  | 
|  373                              std::move(display_modes), |  | 
|  374                              edid_parser.edid(), |  | 
|  375                              current_mode, |  | 
|  376                              native_mode, |  | 
|  377                              output, |  | 
|  378                              crtc, |  | 
|  379                              index); |  | 
|  380  |  | 
|  381   VLOG(1) << "Found display " << cached_outputs_.size() << ":" |  | 
|  382           << " output=" << output << " crtc=" << crtc |  | 
|  383           << " current_mode=" << current_mode_id; |  | 
|  384  |  | 
|  385   return display_snapshot; |  | 
|  386 } |  | 
|  387  |  | 
|  388 void NativeDisplayDelegateX11::GetHDCPState( |  | 
|  389     const DisplaySnapshot& output, |  | 
|  390     const GetHDCPStateCallback& callback) { |  | 
|  391   HDCPState state = HDCP_STATE_UNDESIRED; |  | 
|  392   bool success = GetHDCPState(output, &state); |  | 
|  393   callback.Run(success, state); |  | 
|  394 } |  | 
|  395  |  | 
|  396 bool NativeDisplayDelegateX11::GetHDCPState(const DisplaySnapshot& output, |  | 
|  397                                             HDCPState* state) { |  | 
|  398   unsigned char* values = NULL; |  | 
|  399   int actual_format = 0; |  | 
|  400   unsigned long nitems = 0; |  | 
|  401   unsigned long bytes_after = 0; |  | 
|  402   Atom actual_type = None; |  | 
|  403   int success = 0; |  | 
|  404   RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output(); |  | 
|  405   // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom. |  | 
|  406   Atom prop = XInternAtom(display_, kContentProtectionAtomName, False); |  | 
|  407  |  | 
|  408   // TODO(kcwu): Move this to x11_util (similar method calls in this file and |  | 
|  409   // output_util.cc) |  | 
|  410   success = XRRGetOutputProperty(display_, |  | 
|  411                                  output_id, |  | 
|  412                                  prop, |  | 
|  413                                  0, |  | 
|  414                                  100, |  | 
|  415                                  False, |  | 
|  416                                  False, |  | 
|  417                                  AnyPropertyType, |  | 
|  418                                  &actual_type, |  | 
|  419                                  &actual_format, |  | 
|  420                                  &nitems, |  | 
|  421                                  &bytes_after, |  | 
|  422                                  &values); |  | 
|  423   gfx::XScopedPtr<unsigned char> scoped_values(values); |  | 
|  424   if (actual_type == None) { |  | 
|  425     LOG(ERROR) << "Property '" << kContentProtectionAtomName |  | 
|  426                << "' does not exist"; |  | 
|  427     return false; |  | 
|  428   } |  | 
|  429  |  | 
|  430   if (success == Success && actual_type == XA_ATOM && actual_format == 32 && |  | 
|  431       nitems == 1) { |  | 
|  432     Atom value = reinterpret_cast<Atom*>(values)[0]; |  | 
|  433     if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) { |  | 
|  434       *state = HDCP_STATE_UNDESIRED; |  | 
|  435     } else if (value == |  | 
|  436                XInternAtom(display_, kProtectionDesiredAtomName, False)) { |  | 
|  437       *state = HDCP_STATE_DESIRED; |  | 
|  438     } else if (value == |  | 
|  439                XInternAtom(display_, kProtectionEnabledAtomName, False)) { |  | 
|  440       *state = HDCP_STATE_ENABLED; |  | 
|  441     } else { |  | 
|  442       LOG(ERROR) << "Unknown " << kContentProtectionAtomName |  | 
|  443                  << " value: " << value; |  | 
|  444       return false; |  | 
|  445     } |  | 
|  446   } else { |  | 
|  447     LOG(ERROR) << "XRRGetOutputProperty failed"; |  | 
|  448     return false; |  | 
|  449   } |  | 
|  450  |  | 
|  451   VLOG(3) << "HDCP state: success," << *state; |  | 
|  452   return true; |  | 
|  453 } |  | 
|  454  |  | 
|  455 void NativeDisplayDelegateX11::SetHDCPState( |  | 
|  456     const DisplaySnapshot& output, |  | 
|  457     HDCPState state, |  | 
|  458     const SetHDCPStateCallback& callback) { |  | 
|  459   callback.Run(SetHDCPState(output, state)); |  | 
|  460 } |  | 
|  461  |  | 
|  462 bool NativeDisplayDelegateX11::SetHDCPState(const DisplaySnapshot& output, |  | 
|  463                                             HDCPState state) { |  | 
|  464   Atom name = XInternAtom(display_, kContentProtectionAtomName, False); |  | 
|  465   Atom value = None; |  | 
|  466   switch (state) { |  | 
|  467     case HDCP_STATE_UNDESIRED: |  | 
|  468       value = XInternAtom(display_, kProtectionUndesiredAtomName, False); |  | 
|  469       break; |  | 
|  470     case HDCP_STATE_DESIRED: |  | 
|  471       value = XInternAtom(display_, kProtectionDesiredAtomName, False); |  | 
|  472       break; |  | 
|  473     default: |  | 
|  474       NOTREACHED() << "Invalid HDCP state: " << state; |  | 
|  475       return false; |  | 
|  476   } |  | 
|  477   gfx::X11ErrorTracker err_tracker; |  | 
|  478   unsigned char* data = reinterpret_cast<unsigned char*>(&value); |  | 
|  479   RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output(); |  | 
|  480   XRRChangeOutputProperty( |  | 
|  481       display_, output_id, name, XA_ATOM, 32, PropModeReplace, data, 1); |  | 
|  482   if (err_tracker.FoundNewError()) { |  | 
|  483     LOG(ERROR) << "XRRChangeOutputProperty failed"; |  | 
|  484     return false; |  | 
|  485   } else { |  | 
|  486     return true; |  | 
|  487   } |  | 
|  488 } |  | 
|  489  |  | 
|  490 void NativeDisplayDelegateX11::DestroyUnusedCrtcs() { |  | 
|  491   CHECK(screen_) << "Server not grabbed"; |  | 
|  492  |  | 
|  493   for (int i = 0; i < screen_->ncrtc; ++i) { |  | 
|  494     bool in_use = false; |  | 
|  495     for (ScopedVector<DisplaySnapshot>::const_iterator it = |  | 
|  496              cached_outputs_.begin(); |  | 
|  497          it != cached_outputs_.end(); |  | 
|  498          ++it) { |  | 
|  499       DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it); |  | 
|  500       if (screen_->crtcs[i] == x11_output->crtc()) { |  | 
|  501         in_use = true; |  | 
|  502         break; |  | 
|  503       } |  | 
|  504     } |  | 
|  505  |  | 
|  506     if (!in_use) |  | 
|  507       ConfigureCrtc(screen_->crtcs[i], None, None, 0, 0); |  | 
|  508   } |  | 
|  509 } |  | 
|  510  |  | 
|  511 void NativeDisplayDelegateX11::UpdateCrtcsForNewFramebuffer( |  | 
|  512     const gfx::Size& min_screen_size) { |  | 
|  513   CHECK(screen_) << "Server not grabbed"; |  | 
|  514   // Setting the screen size will fail if any CRTC doesn't fit afterwards. |  | 
|  515   // At the same time, turning CRTCs off and back on uses up a lot of time. |  | 
|  516   // This function tries to be smart to avoid too many off/on cycles: |  | 
|  517   // - We set the new modes on CRTCs, if they fit in both the old and new |  | 
|  518   //   FBs, and park them at (0,0) |  | 
|  519   // - We disable the CRTCs we will need but don't fit in the old FB. Those |  | 
|  520   //   will be reenabled after the resize. |  | 
|  521   // We don't worry about the cached state of the outputs here since we are |  | 
|  522   // not interested in the state we are setting - we just try to get the CRTCs |  | 
|  523   // out of the way so we can rebuild the frame buffer. |  | 
|  524   gfx::Rect fb_rect(min_screen_size); |  | 
|  525   for (ScopedVector<DisplaySnapshot>::const_iterator it = |  | 
|  526            cached_outputs_.begin(); |  | 
|  527        it != cached_outputs_.end(); |  | 
|  528        ++it) { |  | 
|  529     DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it); |  | 
|  530     const DisplayMode* mode_info = x11_output->current_mode(); |  | 
|  531     RROutput output = x11_output->output(); |  | 
|  532     RRMode mode = None; |  | 
|  533  |  | 
|  534     if (mode_info) { |  | 
|  535       mode = static_cast<const DisplayModeX11*>(mode_info)->mode_id(); |  | 
|  536  |  | 
|  537       if (!fb_rect.Contains(gfx::Rect(mode_info->size()))) { |  | 
|  538         // In case our CRTC doesn't fit in common area of our current and about |  | 
|  539         // to be resized framebuffer, disable it. |  | 
|  540         // It'll get reenabled after we resize the framebuffer. |  | 
|  541         mode = None; |  | 
|  542         output = None; |  | 
|  543         mode_info = NULL; |  | 
|  544       } |  | 
|  545     } |  | 
|  546  |  | 
|  547     ConfigureCrtc(x11_output->crtc(), mode, output, 0, 0); |  | 
|  548   } |  | 
|  549 } |  | 
|  550  |  | 
|  551 bool NativeDisplayDelegateX11::IsOutputAspectPreservingScaling(RROutput id) { |  | 
|  552   Atom scaling_prop = XInternAtom(display_, "scaling mode", False); |  | 
|  553   Atom full_aspect_atom = XInternAtom(display_, "Full aspect", False); |  | 
|  554   if (scaling_prop == None || full_aspect_atom == None) |  | 
|  555     return false; |  | 
|  556  |  | 
|  557   int nprop = 0; |  | 
|  558   gfx::XScopedPtr<Atom[]> props(XRRListOutputProperties(display_, id, &nprop)); |  | 
|  559   for (int j = 0; j < nprop; j++) { |  | 
|  560     Atom prop = props[j]; |  | 
|  561     if (scaling_prop == prop) { |  | 
|  562       unsigned char* values = NULL; |  | 
|  563       int actual_format; |  | 
|  564       unsigned long nitems; |  | 
|  565       unsigned long bytes_after; |  | 
|  566       Atom actual_type; |  | 
|  567       int success; |  | 
|  568  |  | 
|  569       success = XRRGetOutputProperty(display_, |  | 
|  570                                      id, |  | 
|  571                                      prop, |  | 
|  572                                      0, |  | 
|  573                                      100, |  | 
|  574                                      False, |  | 
|  575                                      False, |  | 
|  576                                      AnyPropertyType, |  | 
|  577                                      &actual_type, |  | 
|  578                                      &actual_format, |  | 
|  579                                      &nitems, |  | 
|  580                                      &bytes_after, |  | 
|  581                                      &values); |  | 
|  582       gfx::XScopedPtr<unsigned char> scoped_value(values); |  | 
|  583       if (success == Success && actual_type == XA_ATOM && actual_format == 32 && |  | 
|  584           nitems == 1) { |  | 
|  585         Atom value = reinterpret_cast<Atom*>(values)[0]; |  | 
|  586         if (full_aspect_atom == value) |  | 
|  587           return true; |  | 
|  588       } |  | 
|  589     } |  | 
|  590   } |  | 
|  591   return false; |  | 
|  592 } |  | 
|  593  |  | 
|  594  |  | 
|  595 std::vector<ColorCalibrationProfile> |  | 
|  596 NativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles( |  | 
|  597     const DisplaySnapshot& output) { |  | 
|  598   // TODO(mukai|marcheu): Checks the system data and fills the result. |  | 
|  599   // Note that the order would be Dynamic -> Standard -> Movie -> Reading. |  | 
|  600   return std::vector<ColorCalibrationProfile>(); |  | 
|  601 } |  | 
|  602  |  | 
|  603 bool NativeDisplayDelegateX11::SetColorCalibrationProfile( |  | 
|  604     const DisplaySnapshot& output, |  | 
|  605     ColorCalibrationProfile new_profile) { |  | 
|  606   const DisplaySnapshotX11& x11_output = |  | 
|  607       static_cast<const DisplaySnapshotX11&>(output); |  | 
|  608  |  | 
|  609   XRRCrtcGamma* gamma_ramp = CreateGammaRampForProfile(x11_output, new_profile); |  | 
|  610  |  | 
|  611   if (!gamma_ramp) |  | 
|  612     return false; |  | 
|  613  |  | 
|  614   int gamma_ramp_size = XRRGetCrtcGammaSize(display_, x11_output.crtc()); |  | 
|  615   XRRSetCrtcGamma(display_, |  | 
|  616                   x11_output.crtc(), |  | 
|  617                   ResampleGammaRamp(gamma_ramp, gamma_ramp_size)); |  | 
|  618   XRRFreeGamma(gamma_ramp); |  | 
|  619   return true; |  | 
|  620 } |  | 
|  621  |  | 
|  622 XRRCrtcGamma* NativeDisplayDelegateX11::CreateGammaRampForProfile( |  | 
|  623     const DisplaySnapshotX11& x11_output, |  | 
|  624     ColorCalibrationProfile new_profile) { |  | 
|  625   // TODO(mukai|marcheu): Creates the appropriate gamma ramp data from the |  | 
|  626   // profile enum. It would be served by the vendor. |  | 
|  627   return NULL; |  | 
|  628 } |  | 
|  629  |  | 
|  630 bool NativeDisplayDelegateX11::SetColorCorrection( |  | 
|  631     const ui::DisplaySnapshot& output, |  | 
|  632     const std::vector<GammaRampRGBEntry>& degamma_lut, |  | 
|  633     const std::vector<GammaRampRGBEntry>& gamma_lut, |  | 
|  634     const std::vector<float>& correction_matrix) { |  | 
|  635   NOTIMPLEMENTED(); |  | 
|  636   return false; |  | 
|  637 } |  | 
|  638  |  | 
|  639 void NativeDisplayDelegateX11::DrawBackground() { |  | 
|  640   if (!background_color_argb_) |  | 
|  641     return; |  | 
|  642   // Configuring CRTCs/Framebuffer clears the boot screen image.  Paint the |  | 
|  643   // same background color after updating framebuffer to minimize the |  | 
|  644   // duration of black screen at boot time. |  | 
|  645   XColor color; |  | 
|  646   Colormap colormap = DefaultColormap(display_, 0); |  | 
|  647   // XColor uses 16 bits per color. |  | 
|  648   color.red = (background_color_argb_ & 0x00FF0000) >> 8; |  | 
|  649   color.green = (background_color_argb_ & 0x0000FF00); |  | 
|  650   color.blue = (background_color_argb_ & 0x000000FF) << 8; |  | 
|  651   color.flags = DoRed | DoGreen | DoBlue; |  | 
|  652   XAllocColor(display_, colormap, &color); |  | 
|  653  |  | 
|  654   GC gc = XCreateGC(display_, window_, 0, 0); |  | 
|  655   XSetForeground(display_, gc, color.pixel); |  | 
|  656   XSetFillStyle(display_, gc, FillSolid); |  | 
|  657   int width = DisplayWidth(display_, DefaultScreen(display_)); |  | 
|  658   int height = DisplayHeight(display_, DefaultScreen(display_)); |  | 
|  659   XFillRectangle(display_, window_, gc, 0, 0, width, height); |  | 
|  660   XFreeGC(display_, gc); |  | 
|  661   XFreeColors(display_, colormap, &color.pixel, 1, 0); |  | 
|  662 } |  | 
|  663  |  | 
|  664 }  // namespace ui |  | 
| OLD | NEW |