1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
6 #define UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_
15 #include "base/event_types.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/observer_list.h"
19 #include "base/timer/timer.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
21 #include "ui/display/chromeos/query_content_protection_task.h"
22 #include "ui/display/display_export.h"
23 #include "ui/display/types/display_constants.h"
24 #include "ui/display/types/native_display_observer.h"
25 #include "ui/gfx/geometry/size.h"
33 struct DisplayConfigureRequest
;
34 struct GammaRampRGBEntry
;
35 class DisplayLayoutManager
;
37 class DisplaySnapshot
;
38 class NativeDisplayDelegate
;
39 class UpdateDisplayConfigurationTask
;
41 // This class interacts directly with the system display configurator.
42 class DISPLAY_EXPORT DisplayConfigurator
: public NativeDisplayObserver
{
44 typedef uint64_t ContentProtectionClientId
;
45 static const ContentProtectionClientId kInvalidClientId
= 0;
47 typedef base::Callback
<void(bool /* success */)> ConfigurationCallback
;
49 typedef base::Callback
<void(bool /* success */)> EnableProtectionCallback
;
51 struct QueryProtectionResponse
{
52 // True if the query succeeded, false otherwise.
55 // The type of connected display links, which is a bitmask of
56 // DisplayConnectionType values.
57 uint32_t link_mask
= 0;
59 // The desired protection methods, which is a bitmask of the
60 // ContentProtectionMethod values.
61 uint32_t protection_mask
= 0;
64 typedef base::Callback
<void(const QueryProtectionResponse
&)>
65 QueryProtectionCallback
;
67 typedef base::Callback
<void(bool /* success */)> DisplayControlCallback
;
69 typedef std::vector
<DisplaySnapshot
*> DisplayStateList
;
71 // Mapping a display_id to a protection request bitmask.
72 typedef std::map
<int64_t, uint32_t> ContentProtections
;
76 virtual ~Observer() {}
78 // Called after the display mode has been changed. |display| contains the
79 // just-applied configuration. Note that the X server is no longer grabbed
80 // when this method is called, so the actual configuration could've changed
82 virtual void OnDisplayModeChanged(
83 const DisplayStateList
& displays
) {}
85 // Called after a display mode change attempt failed. |displays| contains
86 // displays that are detected when failed.
87 // |failed_new_state| is the new state which the system failed to enter.
88 virtual void OnDisplayModeChangeFailed(
89 const DisplayStateList
& displays
,
90 MultipleDisplayState failed_new_state
) {}
93 // Interface for classes that make decisions about which display state
95 class StateController
{
97 virtual ~StateController() {}
99 // Called when displays are detected.
100 virtual MultipleDisplayState
GetStateForDisplayIds(
101 const ui::DisplayConfigurator::DisplayStateList
& outputs
) const = 0;
103 // Queries the resolution (|size|) in pixels to select display mode for the
105 virtual bool GetResolutionForDisplayId(int64_t display_id
,
106 gfx::Size
* size
) const = 0;
109 // Interface for classes that implement software based mirroring.
110 class SoftwareMirroringController
{
112 virtual ~SoftwareMirroringController() {}
114 // Called when the hardware mirroring failed.
115 virtual void SetSoftwareMirroring(bool enabled
) = 0;
116 virtual bool SoftwareMirroringEnabled() const = 0;
119 // Helper class used by tests.
122 TestApi(DisplayConfigurator
* configurator
) : configurator_(configurator
) {}
125 // If |configure_timer_| is started, stops the timer, runs
126 // ConfigureDisplays(), and returns true; returns false otherwise.
127 bool TriggerConfigureTimeout() WARN_UNUSED_RESULT
;
130 DisplayConfigurator
* configurator_
; // not owned
132 DISALLOW_COPY_AND_ASSIGN(TestApi
);
135 // Flags that can be passed to SetDisplayPower().
136 static const int kSetDisplayPowerNoFlags
;
137 // Configure displays even if the passed-in state matches |power_state_|.
138 static const int kSetDisplayPowerForceProbe
;
139 // Do not change the state if multiple displays are connected or if the
140 // only connected display is external.
141 static const int kSetDisplayPowerOnlyIfSingleInternalDisplay
;
143 // Gap between screens so cursor at bottom of active display doesn't
144 // partially appear on top of inactive display. Higher numbers guard
145 // against larger cursors, but also waste more memory.
146 // For simplicity, this is hard-coded to avoid the complexity of always
147 // determining the DPI of the screen and rationalizing which screen we
148 // need to use for the DPI calculation.
149 // See crbug.com/130188 for initial discussion.
150 static const int kVerticalGap
= 60;
152 // Returns the mode within |display| that matches the given size with highest
153 // refresh rate. Returns None if no matching display was found.
154 static const DisplayMode
* FindDisplayModeMatchingSize(
155 const DisplaySnapshot
& display
,
156 const gfx::Size
& size
);
158 DisplayConfigurator();
159 ~DisplayConfigurator() override
;
161 MultipleDisplayState
display_state() const { return current_display_state_
; }
162 chromeos::DisplayPowerState
requested_power_state() const {
163 return requested_power_state_
;
165 const gfx::Size
framebuffer_size() const { return framebuffer_size_
; }
166 const std::vector
<DisplaySnapshot
*>& cached_displays() const {
167 return cached_displays_
;
170 // Called when an external process no longer needs to control the display
171 // and Chrome can take control.
172 void TakeControl(const DisplayControlCallback
& callback
);
174 // Called when an external process needs to control the display and thus
175 // Chrome should relinquish it.
176 void RelinquishControl(const DisplayControlCallback
& callback
);
178 void set_state_controller(StateController
* controller
) {
179 state_controller_
= controller
;
181 void set_mirroring_controller(SoftwareMirroringController
* controller
) {
182 mirroring_controller_
= controller
;
185 // Replaces |native_display_delegate_| with the delegate passed in and sets
186 // |configure_display_| to true. Should be called before Init().
187 void SetDelegateForTesting(
188 scoped_ptr
<NativeDisplayDelegate
> display_delegate
);
190 // Sets the initial value of |power_state_|. Must be called before Start().
191 void SetInitialDisplayPower(chromeos::DisplayPowerState power_state
);
193 // Initialization, must be called right after constructor.
194 // |is_panel_fitting_enabled| indicates hardware panel fitting support.
195 void Init(bool is_panel_fitting_enabled
);
197 // Does initial configuration of displays during startup.
198 // If |background_color_argb| is non zero and there are multiple displays,
199 // DisplayConfigurator sets the background color of X's RootWindow to this
201 void ForceInitialConfigure(uint32_t background_color_argb
);
203 // Stop handling display configuration events/requests.
204 void PrepareForExit();
206 // Called when powerd notifies us that some set of displays should be turned
207 // on or off. This requires enabling or disabling the CRTC associated with
208 // the display(s) in question so that the low power state is engaged.
209 // |flags| contains bitwise-or-ed kSetDisplayPower* values. After the
210 // configuration finishes |callback| is called with the status of the
212 void SetDisplayPower(chromeos::DisplayPowerState power_state
,
214 const ConfigurationCallback
& callback
);
216 // Force switching the display mode to |new_state|. Returns false if
217 // switching failed (possibly because |new_state| is invalid for the
218 // current set of connected displays).
219 void SetDisplayMode(MultipleDisplayState new_state
);
221 // NativeDisplayDelegate::Observer overrides:
222 void OnConfigurationChanged() override
;
224 void AddObserver(Observer
* observer
);
225 void RemoveObserver(Observer
* observer
);
227 // Sets all the displays into pre-suspend mode; usually this means
228 // configure them for their resume state. This allows faster resume on
229 // machines where display configuration is slow. On completion of the display
230 // configuration |callback| is executed.
231 void SuspendDisplays(const ConfigurationCallback
& callback
);
233 // Reprobes displays to handle changes made while the system was
235 void ResumeDisplays();
237 // Registers a client for display protection and requests a client id. Returns
238 // 0 if requesting failed.
239 ContentProtectionClientId
RegisterContentProtectionClient();
241 // Unregisters the client.
242 void UnregisterContentProtectionClient(ContentProtectionClientId client_id
);
244 // Queries link status and protection status. |callback| is used to respond
246 void QueryContentProtectionStatus(ContentProtectionClientId client_id
,
248 const QueryProtectionCallback
& callback
);
250 // Requests the desired protection methods.
251 // |protection_mask| is the desired protection methods, which is a bitmask
252 // of the ContentProtectionMethod values.
253 // Returns true when the protection request has been made.
254 void EnableContentProtection(ContentProtectionClientId client_id
,
256 uint32_t protection_mask
,
257 const EnableProtectionCallback
& callback
);
259 // Checks the available color profiles for |display_id| and fills the result
261 std::vector
<ui::ColorCalibrationProfile
> GetAvailableColorCalibrationProfiles(
264 // Updates the color calibration to |new_profile|.
265 bool SetColorCalibrationProfile(int64_t display_id
,
266 ui::ColorCalibrationProfile new_profile
);
268 // Sets the gamma ramp for |display_id| to the values in |lut|.
269 bool SetGammaRamp(int64_t display_id
,
270 const std::vector
<GammaRampRGBEntry
>& lut
);
273 class DisplayLayoutManagerImpl
;
275 // Mapping a client to its protection request.
276 typedef std::map
<ContentProtectionClientId
, ContentProtections
>
279 // Performs platform specific delegate initialization.
280 scoped_ptr
<NativeDisplayDelegate
> CreatePlatformNativeDisplayDelegate();
282 // Configures displays. Invoked by |configure_timer_|.
283 void ConfigureDisplays();
285 // Restores |requested_power_state_| after the system has resumed,
286 // additionally forcing a probe. Invoked by |configure_timer_|.
287 void RestoreRequestedPowerStateAfterResume();
289 // Notifies observers about an attempted state change.
290 void NotifyObservers(bool success
, MultipleDisplayState attempted_state
);
292 // Returns the display state that should be used with |cached_displays_| while
294 MultipleDisplayState
ChooseDisplayState(
295 chromeos::DisplayPowerState power_state
) const;
297 // Applies display protections according to requests.
298 bool ApplyProtections(const ContentProtections
& requests
);
300 // If |configuration_task_| isn't initialized, initializes it and starts the
301 // configuration task.
302 void RunPendingConfiguration();
304 // Callback for |configuration_taks_|. When the configuration process finishes
305 // this is called with the result (|success|) and the updated display state.
306 void OnConfigured(bool success
,
307 const std::vector
<DisplaySnapshot
*>& displays
,
308 const gfx::Size
& framebuffer_size
,
309 MultipleDisplayState new_display_state
,
310 chromeos::DisplayPowerState new_power_state
);
312 // Helps in identifying if a configuration task needs to be scheduled.
313 // Return true if any of the |requested_*| parameters have been updated. False
315 bool ShouldRunConfigurationTask() const;
317 // Helper functions which will call the callbacks in
318 // |in_progress_configuration_callbacks_| and
319 // |queued_configuration_callbacks_| and clear the lists after. |success| is
320 // the configuration status used when calling the callbacks.
321 void CallAndClearInProgressCallbacks(bool success
);
322 void CallAndClearQueuedCallbacks(bool success
);
324 // Content protection callbacks called by the tasks when they finish. These
325 // are responsible for destroying the task, replying to the caller that made
326 // the task and starting the a new content protection task if one is queued.
327 void OnContentProtectionQueried(
328 ContentProtectionClientId client_id
,
330 QueryContentProtectionTask::Response response
);
331 void OnContentProtectionEnabled(ContentProtectionClientId client_id
,
333 uint32_t desired_method_mask
,
335 void OnContentProtectionClientUnregistered(bool success
);
337 // Callbacks used to signal when the native platform has released/taken
339 void OnDisplayControlTaken(const DisplayControlCallback
& callback
,
341 void OnDisplayControlRelinquished(const DisplayControlCallback
& callback
,
344 StateController
* state_controller_
;
345 SoftwareMirroringController
* mirroring_controller_
;
346 scoped_ptr
<NativeDisplayDelegate
> native_display_delegate_
;
348 // Used to enable modes which rely on panel fitting.
349 bool is_panel_fitting_enabled_
;
351 // This is detected by the constructor to determine whether or not we should
352 // be enabled. If we aren't running on Chrome OS, we can't assume that the
353 // Xrandr X11 extension or the Ozone underlying display hotplug system are
355 // If this flag is set to false, any attempts to change the display
356 // configuration to immediately fail without changing the state.
357 bool configure_display_
;
359 // Current configuration state.
360 MultipleDisplayState current_display_state_
;
361 chromeos::DisplayPowerState current_power_state_
;
363 // Pending requests. These values are used when triggering the next display
366 // Stores the user requested state or INVALID if nothing was requested.
367 MultipleDisplayState requested_display_state_
;
369 // Stores the requested power state.
370 chromeos::DisplayPowerState requested_power_state_
;
372 // True if |requested_power_state_| has been changed due to a user request.
373 bool requested_power_state_change_
;
375 // Bitwise-or value of the |kSetDisplayPower*| flags defined above.
376 int requested_power_flags_
;
378 // List of callbacks from callers waiting for the display configuration to
379 // start/finish. Note these callbacks belong to the pending request, not a
380 // request currently active.
381 std::vector
<ConfigurationCallback
> queued_configuration_callbacks_
;
383 // List of callbacks belonging to the currently running display configuration
385 std::vector
<ConfigurationCallback
> in_progress_configuration_callbacks_
;
387 std::queue
<base::Closure
> content_protection_tasks_
;
388 std::queue
<QueryProtectionCallback
> query_protection_callbacks_
;
389 std::queue
<EnableProtectionCallback
> enable_protection_callbacks_
;
391 // True if the caller wants to force the display configuration process.
392 bool force_configure_
;
394 // Most-recently-used display configuration. Note that the actual
395 // configuration changes asynchronously.
396 DisplayStateList cached_displays_
;
398 // Most-recently-used framebuffer size.
399 gfx::Size framebuffer_size_
;
401 base::ObserverList
<Observer
> observers_
;
403 // The timer to delay configuring displays. This is used to aggregate multiple
404 // display configuration events when they are reported in short time spans.
405 // See comment for NativeDisplayEventDispatcherX11 for more details.
406 base::OneShotTimer
<DisplayConfigurator
> configure_timer_
;
408 // Id for next display protection client.
409 ContentProtectionClientId next_display_protection_client_id_
;
411 // Display protection requests of each client.
412 ProtectionRequests client_protection_requests_
;
414 // Display controlled by an external entity.
415 bool display_externally_controlled_
;
417 // True if a TakeControl or RelinquishControl has been called but the response
418 // hasn't arrived yet.
419 bool display_control_changing_
;
421 // Whether the displays are currently suspended.
422 bool displays_suspended_
;
424 scoped_ptr
<DisplayLayoutManager
> layout_manager_
;
426 scoped_ptr
<UpdateDisplayConfigurationTask
> configuration_task_
;
428 // This must be the last variable.
429 base::WeakPtrFactory
<DisplayConfigurator
> weak_ptr_factory_
;
431 DISALLOW_COPY_AND_ASSIGN(DisplayConfigurator
);
436 #endif // UI_DISPLAY_CHROMEOS_DISPLAY_CONFIGURATOR_H_