15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/display/chromeos/x11/native_display_delegate_x11.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/Xatom.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/Xlib.h>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/extensions/dpms.h>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <X11/extensions/Xrandr.h>
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <X11/extensions/XInput2.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include <utility>
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/stl_util.h"
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/display/chromeos/x11/display_mode_x11.h"
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/display/chromeos/x11/display_snapshot_x11.h"
19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/display/chromeos/x11/display_util_x11.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/display/types/native_display_observer.h"
220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "ui/display/util/x11/edid_parser_x11.h"
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/events/platform/platform_event_source.h"
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/gfx/geometry/rect.h"
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "ui/gfx/x/x11_error_tracker.h"
26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "ui/gfx/x/x11_types.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ui {
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// DPI measurements.
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const float kMmInInch = 25.4;
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const float kDpi96 = 96.0;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const float kPixelsToMmScale = kMmInInch / kDpi96;
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kContentProtectionAtomName[] = "Content Protection";
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kProtectionUndesiredAtomName[] = "Undesired";
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kProtectionDesiredAtomName[] = "Desired";
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kProtectionEnabledAtomName[] = "Enabled";
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)RRMode GetOutputNativeMode(const XRROutputInfo* output_info) {
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return output_info->nmode > 0 ? output_info->modes[0] : None;
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)XRRCrtcGamma* ResampleGammaRamp(XRRCrtcGamma* gamma_ramp, int gamma_ramp_size) {
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (gamma_ramp->size == gamma_ramp_size)
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return gamma_ramp;
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#define RESAMPLE(array, i, r) \
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  array[i] + (array[i + 1] - array[i]) * r / gamma_ramp_size
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRCrtcGamma* resampled = XRRAllocGamma(gamma_ramp_size);
5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  for (int i = 0; i < gamma_ramp_size; ++i) {
5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int base_index = gamma_ramp->size * i / gamma_ramp_size;
5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    int remaining = gamma_ramp->size * i % gamma_ramp_size;
5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (base_index < gamma_ramp->size - 1) {
5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->red[i] = RESAMPLE(gamma_ramp->red, base_index, remaining);
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->green[i] = RESAMPLE(gamma_ramp->green, base_index, remaining);
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->blue[i] = RESAMPLE(gamma_ramp->blue, base_index, remaining);
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else {
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->red[i] = gamma_ramp->red[gamma_ramp->size - 1];
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->green[i] = gamma_ramp->green[gamma_ramp->size - 1];
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      resampled->blue[i] = gamma_ramp->blue[gamma_ramp->size - 1];
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#undef RESAMPLE
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRFreeGamma(gamma_ramp);
7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return resampled;
7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// NativeDisplayDelegateX11::HelperDelegateX11
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class NativeDisplayDelegateX11::HelperDelegateX11
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    : public NativeDisplayDelegateX11::HelperDelegate {
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  HelperDelegateX11(NativeDisplayDelegateX11* delegate) : delegate_(delegate) {}
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~HelperDelegateX11() {}
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // NativeDisplayDelegateX11::HelperDelegate overrides:
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void UpdateXRandRConfiguration(const base::NativeEvent& event)
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OVERRIDE {
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    XRRUpdateConfiguration(event);
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual const std::vector<DisplaySnapshot*>& GetCachedDisplays() const
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      OVERRIDE {
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return delegate_->cached_outputs_.get();
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void NotifyDisplayObservers() OVERRIDE {
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FOR_EACH_OBSERVER(
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        NativeDisplayObserver, delegate_->observers_, OnConfigurationChanged());
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  NativeDisplayDelegateX11* delegate_;
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HelperDelegateX11);
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// NativeDisplayDelegateX11 implementation:
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NativeDisplayDelegateX11::NativeDisplayDelegateX11()
108a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : display_(gfx::GetXDisplay()),
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      window_(DefaultRootWindow(display_)),
1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      screen_(NULL),
1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      background_color_argb_(0) {}
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)NativeDisplayDelegateX11::~NativeDisplayDelegateX11() {
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (ui::PlatformEventSource::GetInstance()) {
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        platform_event_dispatcher_.get());
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(modes_.begin(), modes_.end());
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void NativeDisplayDelegateX11::Initialize() {
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int error_base_ignored = 0;
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int xrandr_event_base = 0;
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  XRRQueryExtension(display_, &xrandr_event_base, &error_base_ignored);
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  helper_delegate_.reset(new HelperDelegateX11(this));
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  platform_event_dispatcher_.reset(new NativeDisplayEventDispatcherX11(
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      helper_delegate_.get(), xrandr_event_base));
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (ui::PlatformEventSource::GetInstance()) {
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        platform_event_dispatcher_.get());
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NativeDisplayDelegateX11::GrabServer() {
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(!screen_) << "Server already grabbed";
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  XGrabServer(display_);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  screen_ = XRRGetScreenResources(display_, window_);
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_);
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NativeDisplayDelegateX11::UngrabServer() {
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  XRRFreeScreenResources(screen_);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  screen_ = NULL;
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  XUngrabServer(display_);
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // crbug.com/366125
1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  XFlush(display_);
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); }
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) {
1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  background_color_argb_ = color_argb;
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NativeDisplayDelegateX11::ForceDPMSOn() {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(DPMSEnable(display_));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(DPMSForceLevel(display_, DPMSModeOn));
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstd::vector<DisplaySnapshot*> NativeDisplayDelegateX11::GetDisplays() {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  cached_outputs_.clear();
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RRCrtc last_used_crtc = None;
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  InitModes();
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (int i = 0; i < screen_->noutput && cached_outputs_.size() < 2; ++i) {
1723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    RROutput output_id = screen_->outputs[i];
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id);
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (output_info->connection == RR_Connected) {
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      DisplaySnapshotX11* output =
17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          InitDisplaySnapshot(output_id, output_info, &last_used_crtc, i);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      cached_outputs_.push_back(output);
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    XRRFreeOutputInfo(output_info);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return cached_outputs_.get();
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void NativeDisplayDelegateX11::AddMode(const DisplaySnapshot& output,
18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                       const DisplayMode* mode) {
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  CHECK(mode) << "Must add valid mode";
18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
19023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const DisplaySnapshotX11& x11_output =
19123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      static_cast<const DisplaySnapshotX11&>(output);
19223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RRMode mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
19323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
194c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  VLOG(1) << "AddDisplayMode: output=" << x11_output.output()
19523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          << " mode=" << mode_id;
19623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRAddOutputMode(display_, x11_output.output(), mode_id);
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
19923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool NativeDisplayDelegateX11::Configure(const DisplaySnapshot& output,
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         const DisplayMode* mode,
20123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                         const gfx::Point& origin) {
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const DisplaySnapshotX11& x11_output =
20323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      static_cast<const DisplaySnapshotX11&>(output);
20423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RRMode mode_id = None;
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (mode)
20623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
20723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
20823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return ConfigureCrtc(
20923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      x11_output.crtc(), mode_id, x11_output.output(), origin.x(), origin.y());
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NativeDisplayDelegateX11::ConfigureCrtc(RRCrtc crtc,
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             RRMode mode,
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             RROutput output,
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             int x,
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             int y) {
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VLOG(1) << "ConfigureCrtc: crtc=" << crtc << " mode=" << mode
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          << " output=" << output << " x=" << x << " y=" << y;
220ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a
221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Status, which is typically 0 for failure and 1 for success. In
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // actuality it returns a RRCONFIGSTATUS, which uses 0 for success.
22323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (XRRSetCrtcConfig(display_,
22423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       screen_,
22523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       crtc,
22623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       CurrentTime,
22723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       x,
22823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       y,
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       mode,
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       RR_Rotate_0,
23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       (output && mode) ? &output : NULL,
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       (output && mode) ? 1 : 0) != RRSetConfigSuccess) {
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    LOG(WARNING) << "Unable to configure CRTC " << crtc << ":"
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 << " mode=" << mode << " output=" << output << " x=" << x
23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                 << " y=" << y;
23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
23723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
23823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void NativeDisplayDelegateX11::CreateFrameBuffer(const gfx::Size& size) {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Size current_screen_size(
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DisplayWidth(display_, DefaultScreen(display_)),
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DisplayHeight(display_, DefaultScreen(display_)));
247010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  VLOG(1) << "CreateFrameBuffer: new=" << size.ToString()
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          << " current=" << current_screen_size.ToString();
250010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DestroyUnusedCrtcs();
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (size == current_screen_size)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Size min_screen_size(current_screen_size);
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  min_screen_size.SetToMin(size);
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  UpdateCrtcsForNewFramebuffer(min_screen_size);
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int mm_width = size.width() * kPixelsToMmScale;
26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int mm_height = size.height() * kPixelsToMmScale;
26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRSetScreenSize(
26323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      display_, window_, size.width(), size.height(), mm_width, mm_height);
2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // We don't wait for root window resize, therefore this end up with drawing
2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // in the old window size, which we care during the boot.
2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DrawBackground();
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Don't redraw the background upon framebuffer change again. This should
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // happen only once after boot.
2700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  background_color_argb_ = 0;
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid NativeDisplayDelegateX11::AddObserver(NativeDisplayObserver* observer) {
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  observers_.AddObserver(observer);
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid NativeDisplayDelegateX11::RemoveObserver(NativeDisplayObserver* observer) {
2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  observers_.RemoveObserver(observer);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void NativeDisplayDelegateX11::InitModes() {
2823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(modes_.begin(), modes_.end());
28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  modes_.clear();
28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < screen_->nmode; ++i) {
28823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const XRRModeInfo& info = screen_->modes[i];
28923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    float refresh_rate = 0.0f;
29023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (info.hTotal && info.vTotal) {
29123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      refresh_rate =
29223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          static_cast<float>(info.dotClock) /
29323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          (static_cast<float>(info.hTotal) * static_cast<float>(info.vTotal));
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
29523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
29623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    modes_.insert(
29723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        std::make_pair(info.id,
29823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                       new DisplayModeX11(gfx::Size(info.width, info.height),
29923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                          info.modeFlags & RR_Interlace,
30023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                          refresh_rate,
30123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                          info.id)));
3023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
30523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)DisplaySnapshotX11* NativeDisplayDelegateX11::InitDisplaySnapshot(
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    RROutput output,
3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    XRROutputInfo* info,
3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    RRCrtc* last_used_crtc,
3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int index) {
31023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int64_t display_id = 0;
311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  bool has_display_id = GetDisplayId(
3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      output, static_cast<uint8_t>(index), &display_id);
31323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
314c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool has_overscan = false;
3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GetOutputOverscanFlag(output, &has_overscan);
316c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
317c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DisplayConnectionType type = GetDisplayConnectionTypeFromName(info->name);
318c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (type == DISPLAY_CONNECTION_TYPE_UNKNOWN)
319a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    LOG(ERROR) << "Unknown link type: " << info->name;
3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Use the index as a valid display ID even if the internal
3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // display doesn't have valid EDID because the index
3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // will never change.
32423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!has_display_id) {
325c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (type == DISPLAY_CONNECTION_TYPE_INTERNAL)
32623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      has_display_id = true;
32723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
32823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Fallback to output index.
32923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    display_id = index;
33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RRMode native_mode_id = GetOutputNativeMode(info);
33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RRMode current_mode_id = None;
33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gfx::Point origin;
3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (info->crtc) {
3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc);
33723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    current_mode_id = crtc_info->mode;
33823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    origin.SetPoint(crtc_info->x, crtc_info->y);
3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    XRRFreeCrtcInfo(crtc_info);
3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
34223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RRCrtc crtc = None;
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Assign a CRTC that isn't already in use.
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < info->ncrtc; ++i) {
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (info->crtcs[i] != *last_used_crtc) {
34623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      crtc = info->crtcs[i];
34723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      *last_used_crtc = crtc;
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
35223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const DisplayMode* current_mode = NULL;
35323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const DisplayMode* native_mode = NULL;
35423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::vector<const DisplayMode*> display_modes;
35523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < info->nmode; ++i) {
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const RRMode mode = info->modes[i];
35823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (modes_.find(mode) != modes_.end()) {
35923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      display_modes.push_back(modes_.at(mode));
36023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
36123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (mode == current_mode_id)
36223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        current_mode = display_modes.back();
36323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      if (mode == native_mode_id)
36423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        native_mode = display_modes.back();
36523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    } else {
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
36723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
3683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplaySnapshotX11* display_snapshot =
37123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      new DisplaySnapshotX11(display_id,
37223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             has_display_id,
37323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             origin,
37423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             gfx::Size(info->mm_width, info->mm_height),
37523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             type,
3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             IsOutputAspectPreservingScaling(output),
377c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                             has_overscan,
3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             GetDisplayName(output),
37923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             display_modes,
38023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             current_mode,
38123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             native_mode,
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                             output,
38323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             crtc,
38423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                             index);
38523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  VLOG(1) << "Found display " << cached_outputs_.size() << ":"
38723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          << " output=" << output << " crtc=" << crtc
38823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          << " current_mode=" << current_mode_id;
38923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return display_snapshot;
3913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
39323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool NativeDisplayDelegateX11::GetHDCPState(const DisplaySnapshot& output,
39423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                            HDCPState* state) {
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned char* values = NULL;
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int actual_format = 0;
3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned long nitems = 0;
3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned long bytes_after = 0;
3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Atom actual_type = None;
4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int success = 0;
40123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
4024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(kcwu): Use X11AtomCache to save round trip time of XInternAtom.
4034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Atom prop = XInternAtom(display_, kContentProtectionAtomName, False);
4044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ok = true;
4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // TODO(kcwu): Move this to x11_util (similar method calls in this file and
4074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // output_util.cc)
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  success = XRRGetOutputProperty(display_,
40923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                 output_id,
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 prop,
4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 0,
4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 100,
4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 False,
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 False,
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 AnyPropertyType,
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &actual_type,
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &actual_format,
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &nitems,
4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 &bytes_after,
4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                 &values);
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (actual_type == None) {
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(ERROR) << "Property '" << kContentProtectionAtomName
4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)               << "' does not exist";
4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ok = false;
4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (success == Success && actual_type == XA_ATOM &&
4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             actual_format == 32 && nitems == 1) {
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Atom value = reinterpret_cast<Atom*>(values)[0];
4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (value == XInternAtom(display_, kProtectionUndesiredAtomName, False)) {
429a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *state = HDCP_STATE_UNDESIRED;
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (value ==
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               XInternAtom(display_, kProtectionDesiredAtomName, False)) {
432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *state = HDCP_STATE_DESIRED;
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (value ==
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               XInternAtom(display_, kProtectionEnabledAtomName, False)) {
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      *state = HDCP_STATE_ENABLED;
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    } else {
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << "Unknown " << kContentProtectionAtomName
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 << " value: " << value;
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ok = false;
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(ERROR) << "XRRGetOutputProperty failed";
4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ok = false;
4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (values)
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    XFree(values);
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(3) << "HDCP state: " << ok << "," << *state;
4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return ok;
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
45223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool NativeDisplayDelegateX11::SetHDCPState(const DisplaySnapshot& output,
45323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                            HDCPState state) {
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Atom name = XInternAtom(display_, kContentProtectionAtomName, False);
4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Atom value = None;
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  switch (state) {
457a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case HDCP_STATE_UNDESIRED:
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      value = XInternAtom(display_, kProtectionUndesiredAtomName, False);
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    case HDCP_STATE_DESIRED:
4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      value = XInternAtom(display_, kProtectionDesiredAtomName, False);
4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      break;
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    default:
4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      NOTREACHED() << "Invalid HDCP state: " << state;
4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
46723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  gfx::X11ErrorTracker err_tracker;
4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned char* data = reinterpret_cast<unsigned char*>(&value);
46923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  XRRChangeOutputProperty(
47123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      display_, output_id, name, XA_ATOM, 32, PropModeReplace, data, 1);
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (err_tracker.FoundNewError()) {
4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    LOG(ERROR) << "XRRChangeOutputProperty failed";
4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
480f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NativeDisplayDelegateX11::DestroyUnusedCrtcs() {
481f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
482f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
483f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (int i = 0; i < screen_->ncrtc; ++i) {
484f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool in_use = false;
485f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (ScopedVector<DisplaySnapshot>::const_iterator it =
486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)             cached_outputs_.begin();
487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         it != cached_outputs_.end();
488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         ++it) {
489f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it);
490f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (screen_->crtcs[i] == x11_output->crtc()) {
491f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        in_use = true;
492f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
493f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
494f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
495f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
496f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!in_use)
497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ConfigureCrtc(screen_->crtcs[i], None, None, 0, 0);
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
499f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
500f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
501f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void NativeDisplayDelegateX11::UpdateCrtcsForNewFramebuffer(
502f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const gfx::Size& min_screen_size) {
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(screen_) << "Server not grabbed";
504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Setting the screen size will fail if any CRTC doesn't fit afterwards.
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // At the same time, turning CRTCs off and back on uses up a lot of time.
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This function tries to be smart to avoid too many off/on cycles:
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // - We set the new modes on CRTCs, if they fit in both the old and new
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   FBs, and park them at (0,0)
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // - We disable the CRTCs we will need but don't fit in the old FB. Those
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //   will be reenabled after the resize.
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We don't worry about the cached state of the outputs here since we are
512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // not interested in the state we are setting - we just try to get the CRTCs
513c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // out of the way so we can rebuild the frame buffer.
514f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  gfx::Rect fb_rect(min_screen_size);
515f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (ScopedVector<DisplaySnapshot>::const_iterator it =
516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           cached_outputs_.begin();
517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       it != cached_outputs_.end();
518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)       ++it) {
519f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DisplaySnapshotX11* x11_output = static_cast<DisplaySnapshotX11*>(*it);
520f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const DisplayMode* mode_info = x11_output->current_mode();
521f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    RROutput output = x11_output->output();
522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RRMode mode = None;
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (mode_info) {
52523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      mode = static_cast<const DisplayModeX11*>(mode_info)->mode_id();
526f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!fb_rect.Contains(gfx::Rect(mode_info->size()))) {
528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // In case our CRTC doesn't fit in common area of our current and about
529f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // to be resized framebuffer, disable it.
530f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // It'll get reenabled after we resize the framebuffer.
531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        mode = None;
532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        output = None;
5333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        mode_info = NULL;
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
537f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ConfigureCrtc(x11_output->crtc(), mode, output, 0, 0);
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NativeDisplayDelegateX11::IsOutputAspectPreservingScaling(RROutput id) {
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool ret = false;
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Atom scaling_prop = XInternAtom(display_, "scaling mode", False);
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Atom full_aspect_atom = XInternAtom(display_, "Full aspect", False);
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (scaling_prop == None || full_aspect_atom == None)
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int nprop = 0;
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Atom* props = XRRListOutputProperties(display_, id, &nprop);
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int j = 0; j < nprop && !ret; j++) {
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Atom prop = props[j];
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (scaling_prop == prop) {
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      unsigned char* values = NULL;
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int actual_format;
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      unsigned long nitems;
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      unsigned long bytes_after;
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      Atom actual_type;
559c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      int success;
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      success = XRRGetOutputProperty(display_,
5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     id,
5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     prop,
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     0,
5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     100,
5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     False,
5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     False,
5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     AnyPropertyType,
5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     &actual_type,
5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     &actual_format,
5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     &nitems,
5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     &bytes_after,
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     &values);
5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (success == Success && actual_type == XA_ATOM && actual_format == 32 &&
5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          nitems == 1) {
576c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        Atom value = reinterpret_cast<Atom*>(values)[0];
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        if (full_aspect_atom == value)
578c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ret = true;
579c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (values)
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        XFree(values);
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (props)
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    XFree(props);
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return ret;
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
590effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
591effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::vector<ColorCalibrationProfile>
592effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochNativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles(
593effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const DisplaySnapshot& output) {
594effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // TODO(mukai|marcheu): Checks the system data and fills the result.
595effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Note that the order would be Dynamic -> Standard -> Movie -> Reading.
596effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return std::vector<ColorCalibrationProfile>();
597effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
598effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
59923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool NativeDisplayDelegateX11::SetColorCalibrationProfile(
60023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const DisplaySnapshot& output,
60123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ColorCalibrationProfile new_profile) {
60223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const DisplaySnapshotX11& x11_output =
60323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      static_cast<const DisplaySnapshotX11&>(output);
60423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
60523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRCrtcGamma* gamma_ramp = CreateGammaRampForProfile(x11_output, new_profile);
60623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
60723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!gamma_ramp)
60823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
60923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
61023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int gamma_ramp_size = XRRGetCrtcGammaSize(display_, x11_output.crtc());
61123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRSetCrtcGamma(display_,
61223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                  x11_output.crtc(),
61323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                  ResampleGammaRamp(gamma_ramp, gamma_ramp_size));
61423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  XRRFreeGamma(gamma_ramp);
61523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
61623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
61723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
61823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)XRRCrtcGamma* NativeDisplayDelegateX11::CreateGammaRampForProfile(
61923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const DisplaySnapshotX11& x11_output,
62023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    ColorCalibrationProfile new_profile) {
62123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(mukai|marcheu): Creates the appropriate gamma ramp data from the
62223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // profile enum. It would be served by the vendor.
62323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return NULL;
62423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
62523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid NativeDisplayDelegateX11::DrawBackground() {
6270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!background_color_argb_)
6280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
6290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Configuring CRTCs/Framebuffer clears the boot screen image.  Paint the
6300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // same background color after updating framebuffer to minimize the
6310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // duration of black screen at boot time.
6320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XColor color;
6330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  Colormap colormap = DefaultColormap(display_, 0);
6340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // XColor uses 16 bits per color.
6350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  color.red = (background_color_argb_ & 0x00FF0000) >> 8;
6360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  color.green = (background_color_argb_ & 0x0000FF00);
6370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  color.blue = (background_color_argb_ & 0x000000FF) << 8;
6380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  color.flags = DoRed | DoGreen | DoBlue;
6390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XAllocColor(display_, colormap, &color);
640a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  GC gc = XCreateGC(display_, window_, 0, 0);
6420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XSetForeground(display_, gc, color.pixel);
6430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XSetFillStyle(display_, gc, FillSolid);
6440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int width = DisplayWidth(display_, DefaultScreen(display_));
6450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int height = DisplayHeight(display_, DefaultScreen(display_));
6460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XFillRectangle(display_, window_, gc, 0, 0, width, height);
6470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XFreeGC(display_, gc);
6480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  XFreeColors(display_, colormap, &color.pixel, 1, 0);
649a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
650a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
651a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace ui
652