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

Side by Side Diff: ui/display/chromeos/x11/native_display_delegate_x11.cc

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

Powered by Google App Engine
This is Rietveld 408576698