Getting rid of GetDefaultProfile(), clean up of ProfileManager (which was in a seriou...
[chromium-blink-merge.git] / chromeos / display / output_configurator.h
blobc927519f799e20c5fb54ae4dad65a489c7d45db7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
6 #define CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_
8 #include <map>
9 #include <string>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/event_types.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/observer_list.h"
17 #include "base/timer/timer.h"
18 #include "chromeos/chromeos_export.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
21 // Forward declarations for Xlib and Xrandr.
22 // This is so unused X definitions don't pollute the namespace.
23 typedef unsigned long XID;
24 typedef XID RROutput;
25 typedef XID RRCrtc;
26 typedef XID RRMode;
28 namespace chromeos {
30 // Used to describe the state of a multi-display configuration.
31 enum OutputState {
32 STATE_INVALID,
33 STATE_HEADLESS,
34 STATE_SINGLE,
35 STATE_DUAL_MIRROR,
36 STATE_DUAL_EXTENDED,
39 // Video output types.
40 enum OutputType {
41 OUTPUT_TYPE_NONE = 0,
42 OUTPUT_TYPE_UNKNOWN = 1 << 0,
43 OUTPUT_TYPE_INTERNAL = 1 << 1,
44 OUTPUT_TYPE_VGA = 1 << 2,
45 OUTPUT_TYPE_HDMI = 1 << 3,
46 OUTPUT_TYPE_DVI = 1 << 4,
47 OUTPUT_TYPE_DISPLAYPORT = 1 << 5,
48 OUTPUT_TYPE_NETWORK = 1 << 6,
51 // Content protection methods applied on video output.
52 enum OutputProtectionMethod {
53 OUTPUT_PROTECTION_METHOD_NONE = 0,
54 OUTPUT_PROTECTION_METHOD_HDCP = 1 << 0,
57 // HDCP protection state.
58 enum HDCPState {
59 HDCP_STATE_UNDESIRED,
60 HDCP_STATE_DESIRED,
61 HDCP_STATE_ENABLED
64 // This class interacts directly with the underlying Xrandr API to manipulate
65 // CTRCs and Outputs.
66 class CHROMEOS_EXPORT OutputConfigurator
67 : public base::MessageLoop::Dispatcher,
68 public base::MessagePumpObserver {
69 public:
70 typedef uint64_t OutputProtectionClientId;
71 static const OutputProtectionClientId kInvalidClientId = 0;
73 struct ModeInfo {
74 ModeInfo();
75 ModeInfo(int width, int height, bool interlaced, float refresh_rate);
77 int width;
78 int height;
79 bool interlaced;
80 float refresh_rate;
83 typedef std::map<RRMode, ModeInfo> ModeInfoMap;
85 struct CoordinateTransformation {
86 // Initialized to the identity transformation.
87 CoordinateTransformation();
89 float x_scale;
90 float x_offset;
91 float y_scale;
92 float y_offset;
95 // Information about an output's current state.
96 struct OutputSnapshot {
97 OutputSnapshot();
98 ~OutputSnapshot();
100 RROutput output;
102 // CRTC that should be used for this output. Not necessarily the CRTC
103 // that XRandR reports is currently being used.
104 RRCrtc crtc;
106 // Mode currently being used by the output.
107 RRMode current_mode;
109 // "Best" mode supported by the output.
110 RRMode native_mode;
112 // Mode used when displaying the same desktop on multiple outputs.
113 RRMode mirror_mode;
115 // User-selected mode for the output.
116 RRMode selected_mode;
118 // Output's origin on the framebuffer.
119 int x;
120 int y;
122 // Output's physical dimensions.
123 uint64 width_mm;
124 uint64 height_mm;
126 // TODO(kcwu): Remove this. Check type == OUTPUT_TYPE_INTERNAL instead.
127 bool is_internal;
128 bool is_aspect_preserving_scaling;
130 // The type of output.
131 OutputType type;
133 // Map from mode IDs to details about the corresponding modes.
134 ModeInfoMap mode_infos;
136 // XInput device ID or 0 if this output isn't a touchscreen.
137 int touch_device_id;
139 CoordinateTransformation transform;
141 // Display id for this output.
142 int64 display_id;
144 bool has_display_id;
146 // This output's index in the array returned by XRandR. Stable even as
147 // outputs are connected or disconnected.
148 int index;
151 class Observer {
152 public:
153 virtual ~Observer() {}
155 // Called after the display mode has been changed. |output| contains the
156 // just-applied configuration. Note that the X server is no longer grabbed
157 // when this method is called, so the actual configuration could've changed
158 // already.
159 virtual void OnDisplayModeChanged(
160 const std::vector<OutputSnapshot>& outputs) {}
162 // Called after a display mode change attempt failed. |failed_new_state| is
163 // the new state which the system failed to enter.
164 virtual void OnDisplayModeChangeFailed(OutputState failed_new_state) {}
167 // Interface for classes that make decisions about which output state
168 // should be used.
169 class StateController {
170 public:
171 virtual ~StateController() {}
173 // Called when displays are detected.
174 virtual OutputState GetStateForDisplayIds(
175 const std::vector<int64>& display_ids) const = 0;
177 // Queries the resolution (|width|x|height|) in pixels
178 // to select output mode for the given display id.
179 virtual bool GetResolutionForDisplayId(int64 display_id,
180 int* width,
181 int* height) const = 0;
184 // Interface for classes that implement software based mirroring.
185 class SoftwareMirroringController {
186 public:
187 virtual ~SoftwareMirroringController() {}
189 // Called when the hardware mirroring failed.
190 virtual void SetSoftwareMirroring(bool enabled) = 0;
193 // Interface for classes that perform actions on behalf of OutputController.
194 class Delegate {
195 public:
196 virtual ~Delegate() {}
198 // Initializes the XRandR extension, saving the base event ID to
199 // |event_base|.
200 virtual void InitXRandRExtension(int* event_base) = 0;
202 // Tells XRandR to update its configuration in response to |event|, an
203 // RRScreenChangeNotify event.
204 virtual void UpdateXRandRConfiguration(const base::NativeEvent& event) = 0;
206 // Grabs the X server and refreshes XRandR-related resources. While
207 // the server is grabbed, other clients are blocked. Must be balanced
208 // by a call to UngrabServer().
209 virtual void GrabServer() = 0;
211 // Ungrabs the server and frees XRandR-related resources.
212 virtual void UngrabServer() = 0;
214 // Flushes all pending requests and waits for replies.
215 virtual void SyncWithServer() = 0;
217 // Sets the window's background color to |color_argb|.
218 virtual void SetBackgroundColor(uint32 color_argb) = 0;
220 // Enables DPMS and forces it to the "on" state.
221 virtual void ForceDPMSOn() = 0;
223 // Returns information about the current outputs. This method may block for
224 // 60 milliseconds or more. The returned outputs are not fully initialized;
225 // the rest of the work happens in
226 // OutputConfigurator::UpdateCachedOutputs().
227 virtual std::vector<OutputSnapshot> GetOutputs() = 0;
229 // Adds |mode| to |output|.
230 virtual void AddOutputMode(RROutput output, RRMode mode) = 0;
232 // Calls XRRSetCrtcConfig() with the given options but some of our default
233 // output count and rotation arguments. Returns true on success.
234 virtual bool ConfigureCrtc(RRCrtc crtc,
235 RRMode mode,
236 RROutput output,
237 int x,
238 int y) = 0;
240 // Called to set the frame buffer (underlying XRR "screen") size. Has
241 // a side-effect of disabling all CRTCs.
242 virtual void CreateFrameBuffer(
243 int width,
244 int height,
245 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) = 0;
247 // Configures XInput's Coordinate Transformation Matrix property.
248 // |touch_device_id| the ID of the touchscreen device to configure.
249 // |ctm| contains the desired transformation parameters. The offsets
250 // in it should be normalized so that 1 corresponds to the X or Y axis
251 // size for the corresponding offset.
252 virtual void ConfigureCTM(int touch_device_id,
253 const CoordinateTransformation& ctm) = 0;
255 // Sends a D-Bus message to the power manager telling it that the
256 // machine is or is not projecting.
257 virtual void SendProjectingStateToPowerManager(bool projecting) = 0;
259 // Gets HDCP state of output.
260 virtual bool GetHDCPState(RROutput id, HDCPState* state) = 0;
262 // Sets HDCP state of output.
263 virtual bool SetHDCPState(RROutput id, HDCPState state) = 0;
266 // Helper class used by tests.
267 class TestApi {
268 public:
269 TestApi(OutputConfigurator* configurator, int xrandr_event_base)
270 : configurator_(configurator),
271 xrandr_event_base_(xrandr_event_base) {}
272 ~TestApi() {}
274 const std::vector<OutputSnapshot>& cached_outputs() const {
275 return configurator_->cached_outputs_;
278 // Dispatches an RRScreenChangeNotify event to |configurator_|.
279 void SendScreenChangeEvent();
281 // Dispatches an RRNotify_OutputChange event to |configurator_|.
282 void SendOutputChangeEvent(RROutput output,
283 RRCrtc crtc,
284 RRMode mode,
285 bool connected);
287 // If |configure_timer_| is started, stops the timer, runs
288 // ConfigureOutputs(), and returns true; returns false otherwise.
289 bool TriggerConfigureTimeout();
291 private:
292 OutputConfigurator* configurator_; // not owned
294 int xrandr_event_base_;
296 DISALLOW_COPY_AND_ASSIGN(TestApi);
299 // Flags that can be passed to SetDisplayPower().
300 static const int kSetDisplayPowerNoFlags = 0;
301 // Configure displays even if the passed-in state matches |power_state_|.
302 static const int kSetDisplayPowerForceProbe = 1 << 0;
303 // Do not change the state if multiple displays are connected or if the
304 // only connected display is external.
305 static const int kSetDisplayPowerOnlyIfSingleInternalDisplay = 1 << 1;
307 // Gap between screens so cursor at bottom of active display doesn't
308 // partially appear on top of inactive display. Higher numbers guard
309 // against larger cursors, but also waste more memory.
310 // For simplicity, this is hard-coded to avoid the complexity of always
311 // determining the DPI of the screen and rationalizing which screen we
312 // need to use for the DPI calculation.
313 // See crbug.com/130188 for initial discussion.
314 static const int kVerticalGap = 60;
316 // Returns a pointer to the ModeInfo struct in |output| corresponding to
317 // |mode|, or NULL if the struct isn't present.
318 static const ModeInfo* GetModeInfo(const OutputSnapshot& output,
319 RRMode mode);
321 // Returns the mode within |output| that matches the given size with highest
322 // refresh rate. Returns None if no matching output was found.
323 static RRMode FindOutputModeMatchingSize(const OutputSnapshot& output,
324 int width,
325 int height);
327 OutputConfigurator();
328 virtual ~OutputConfigurator();
330 OutputState output_state() const { return output_state_; }
331 DisplayPowerState power_state() const { return power_state_; }
333 void set_state_controller(StateController* controller) {
334 state_controller_ = controller;
336 void set_mirroring_controller(SoftwareMirroringController* controller) {
337 mirroring_controller_ = controller;
340 // Replaces |delegate_| with |delegate| and sets |configure_display_| to
341 // true. Should be called before Init().
342 void SetDelegateForTesting(scoped_ptr<Delegate> delegate);
344 // Sets the initial value of |power_state_|. Must be called before Start().
345 void SetInitialDisplayPower(DisplayPowerState power_state);
347 // Initialization, must be called right after constructor.
348 // |is_panel_fitting_enabled| indicates hardware panel fitting support.
349 void Init(bool is_panel_fitting_enabled);
351 // Does initial configuration of displays during startup.
352 // If |background_color_argb| is non zero and there are multiple displays,
353 // OutputConfigurator sets the background color of X's RootWindow to this
354 // color.
355 void Start(uint32 background_color_argb);
357 // Stop handling display configuration events/requests.
358 void Stop();
360 // Called when powerd notifies us that some set of displays should be turned
361 // on or off. This requires enabling or disabling the CRTC associated with
362 // the display(s) in question so that the low power state is engaged.
363 // |flags| contains bitwise-or-ed kSetDisplayPower* values.
364 bool SetDisplayPower(DisplayPowerState power_state, int flags);
366 // Force switching the display mode to |new_state|. Returns false if
367 // switching failed (possibly because |new_state| is invalid for the
368 // current set of connected outputs).
369 bool SetDisplayMode(OutputState new_state);
371 // Called when an RRNotify event is received. The implementation is
372 // interested in the cases of RRNotify events which correspond to output
373 // add/remove events. Note that Output add/remove events are sent in response
374 // to our own reconfiguration operations so spurious events are common.
375 // Spurious events will have no effect.
376 virtual bool Dispatch(const base::NativeEvent& event) OVERRIDE;
378 // Overridden from base::MessagePumpObserver:
379 virtual base::EventStatus WillProcessEvent(
380 const base::NativeEvent& event) OVERRIDE;
381 virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
383 void AddObserver(Observer* observer);
384 void RemoveObserver(Observer* observer);
386 // Sets all the displays into pre-suspend mode; usually this means
387 // configure them for their resume state. This allows faster resume on
388 // machines where display configuration is slow.
389 void SuspendDisplays();
391 // Reprobes displays to handle changes made while the system was
392 // suspended.
393 void ResumeDisplays();
395 const std::map<int, float>& GetMirroredDisplayAreaRatioMap() {
396 return mirrored_display_area_ratio_map_;
399 // Configure outputs with |kConfigureDelayMs| delay,
400 // so that time-consuming ConfigureOutputs() won't be called multiple times.
401 void ScheduleConfigureOutputs();
403 // Registers a client for output protection and requests a client id. Returns
404 // 0 if requesting failed.
405 OutputProtectionClientId RegisterOutputProtectionClient();
407 // Unregisters the client.
408 void UnregisterOutputProtectionClient(OutputProtectionClientId client_id);
410 // Queries link status and protection status.
411 // |link_mask| is the type of connected output links, which is a bitmask of
412 // OutputType values. |protection_mask| is the desired protection methods,
413 // which is a bitmask of the OutputProtectionMethod values.
414 // Returns true on success.
415 bool QueryOutputProtectionStatus(
416 OutputProtectionClientId client_id,
417 int64 display_id,
418 uint32_t* link_mask,
419 uint32_t* protection_mask);
421 // Requests the desired protection methods.
422 // |protection_mask| is the desired protection methods, which is a bitmask
423 // of the OutputProtectionMethod values.
424 // Returns true when the protection request has been made.
425 bool EnableOutputProtection(
426 OutputProtectionClientId client_id,
427 int64 display_id,
428 uint32_t desired_protection_mask);
430 private:
431 // Mapping a display_id to a protection request bitmask.
432 typedef std::map<int64, uint32_t> DisplayProtections;
433 // Mapping a client to its protection request.
434 typedef std::map<OutputProtectionClientId,
435 DisplayProtections> ProtectionRequests;
437 // Updates |cached_outputs_| to contain currently-connected outputs. Calls
438 // |delegate_->GetOutputs()| and then does additional work, like finding the
439 // mirror mode and setting user-preferred modes. Note that the server must be
440 // grabbed via |delegate_->GrabServer()| first.
441 void UpdateCachedOutputs();
443 // Helper method for UpdateCachedOutputs() that initializes the passed-in
444 // outputs' |mirror_mode| fields by looking for a mode in |internal_output|
445 // and |external_output| having the same resolution. Returns false if a shared
446 // mode wasn't found or created.
448 // |try_panel_fitting| allows creating a panel-fitting mode for
449 // |internal_output| instead of only searching for a matching mode (note that
450 // it may lead to a crash if |internal_info| is not capable of panel fitting).
452 // |preserve_aspect| limits the search/creation only to the modes having the
453 // native aspect ratio of |external_output|.
454 bool FindMirrorMode(OutputSnapshot* internal_output,
455 OutputSnapshot* external_output,
456 bool try_panel_fitting,
457 bool preserve_aspect);
459 // Configures outputs.
460 void ConfigureOutputs();
462 // Notifies observers about an attempted state change.
463 void NotifyObservers(bool success, OutputState attempted_state);
465 // Switches to the state specified in |output_state| and |power_state|.
466 // If the hardware mirroring failed and |mirroring_controller_| is set,
467 // it switches to |STATE_DUAL_EXTENDED| and calls |SetSoftwareMirroring()|
468 // to enable software based mirroring.
469 // On success, updates |output_state_|, |power_state_|, and |cached_outputs_|
470 // and returns true.
471 bool EnterStateOrFallBackToSoftwareMirroring(
472 OutputState output_state,
473 DisplayPowerState power_state);
475 // Switches to the state specified in |output_state| and |power_state|.
476 // On success, updates |output_state_|, |power_state_|, and
477 // |cached_outputs_| and returns true.
478 bool EnterState(OutputState output_state, DisplayPowerState power_state);
480 // Returns the output state that should be used with |cached_outputs_| while
481 // in |power_state|.
482 OutputState ChooseOutputState(DisplayPowerState power_state) const;
484 // Computes the relevant transformation for mirror mode.
485 // |output| is the output on which mirror mode is being applied.
486 // Returns the transformation or identity if computations fail.
487 CoordinateTransformation GetMirrorModeCTM(
488 const OutputConfigurator::OutputSnapshot& output);
490 // Computes the relevant transformation for extended mode.
491 // |output| is the output on which extended mode is being applied.
492 // |width| and |height| are the width and height of the combined framebuffer.
493 // Returns the transformation or identity if computations fail.
494 CoordinateTransformation GetExtendedModeCTM(
495 const OutputConfigurator::OutputSnapshot& output,
496 int framebuffer_width,
497 int frame_buffer_height);
499 // Returns the ratio between mirrored mode area and native mode area:
500 // (mirror_mode_width * mirrow_mode_height) / (native_width * native_height)
501 float GetMirroredDisplayAreaRatio(
502 const OutputConfigurator::OutputSnapshot& output);
504 // Applies output protections according to requests.
505 bool ApplyProtections(const DisplayProtections& requests);
507 StateController* state_controller_;
508 SoftwareMirroringController* mirroring_controller_;
509 scoped_ptr<Delegate> delegate_;
511 // Used to enable modes which rely on panel fitting.
512 bool is_panel_fitting_enabled_;
514 // Key of the map is the touch display's id, and the value of the map is the
515 // touch display's area ratio in mirror mode defined as :
516 // mirror_mode_area / native_mode_area.
517 // This is used for scaling touch event's radius when the touch display is in
518 // mirror mode :
519 // new_touch_radius = sqrt(area_ratio) * old_touch_radius
520 std::map<int, float> mirrored_display_area_ratio_map_;
522 // This is detected by the constructor to determine whether or not we should
523 // be enabled. If we aren't running on ChromeOS, we can't assume that the
524 // Xrandr X11 extension is supported.
525 // If this flag is set to false, any attempts to change the output
526 // configuration to immediately fail without changing the state.
527 bool configure_display_;
529 // The base of the event numbers used to represent XRandr events used in
530 // decoding events regarding output add/remove.
531 int xrandr_event_base_;
533 // The current display state.
534 OutputState output_state_;
536 // The current power state.
537 DisplayPowerState power_state_;
539 // Most-recently-used output configuration. Note that the actual
540 // configuration changes asynchronously.
541 std::vector<OutputSnapshot> cached_outputs_;
543 ObserverList<Observer> observers_;
545 // The timer to delay configuring outputs. See also the comments in
546 // Dispatch().
547 scoped_ptr<base::OneShotTimer<OutputConfigurator> > configure_timer_;
549 // Id for next output protection client.
550 OutputProtectionClientId next_output_protection_client_id_;
552 // Output protection requests of each client.
553 ProtectionRequests client_protection_requests_;
555 DISALLOW_COPY_AND_ASSIGN(OutputConfigurator);
558 typedef std::vector<OutputConfigurator::OutputSnapshot> OutputSnapshotList;
560 } // namespace chromeos
562 #endif // CHROMEOS_DISPLAY_OUTPUT_CONFIGURATOR_H_