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