Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / screen_manager.cc
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.
4
5 #include "ui/ozone/platform/dri/screen_manager.h"
6
7 #include <xf86drmMode.h>
8
9 #include "ui/gfx/geometry/point.h"
10 #include "ui/gfx/geometry/rect.h"
11 #include "ui/gfx/geometry/size.h"
12 #include "ui/ozone/platform/dri/crtc_controller.h"
13 #include "ui/ozone/platform/dri/dri_util.h"
14 #include "ui/ozone/platform/dri/dri_wrapper.h"
15 #include "ui/ozone/platform/dri/hardware_display_controller.h"
16 #include "ui/ozone/platform/dri/scanout_buffer.h"
17
18 namespace ui {
19
20 ScreenManager::ScreenManager(DriWrapper* dri,
21                              ScanoutBufferGenerator* buffer_generator)
22     : dri_(dri), buffer_generator_(buffer_generator) {
23 }
24
25 ScreenManager::~ScreenManager() {
26 }
27
28 void ScreenManager::AddDisplayController(DriWrapper* dri,
29                                          uint32_t crtc,
30                                          uint32_t connector) {
31   HardwareDisplayControllers::iterator it = FindDisplayController(crtc);
32   // TODO(dnicoara): Turn this into a DCHECK when async display configuration is
33   // properly supported. (When there can't be a race between forcing initial
34   // display configuration in ScreenManager and NativeDisplayDelegate creating
35   // the display controllers.)
36   if (it != controllers_.end()) {
37     LOG(WARNING) << "Display controller (crtc=" << crtc << ") already present.";
38     return;
39   }
40
41   controllers_.push_back(new HardwareDisplayController(
42       scoped_ptr<CrtcController>(new CrtcController(dri, crtc, connector))));
43 }
44
45 void ScreenManager::RemoveDisplayController(uint32_t crtc) {
46   HardwareDisplayControllers::iterator it = FindDisplayController(crtc);
47   if (it != controllers_.end()) {
48     bool is_mirrored = (*it)->IsMirrored();
49     (*it)->RemoveCrtc(crtc);
50     if (!is_mirrored)
51       controllers_.erase(it);
52   }
53 }
54
55 bool ScreenManager::ConfigureDisplayController(uint32_t crtc,
56                                                uint32_t connector,
57                                                const gfx::Point& origin,
58                                                const drmModeModeInfo& mode) {
59   gfx::Rect modeset_bounds(origin.x(), origin.y(), mode.hdisplay,
60                            mode.vdisplay);
61   HardwareDisplayControllers::iterator it = FindDisplayController(crtc);
62   DCHECK(controllers_.end() != it) << "Display controller (crtc=" << crtc
63                                    << ") doesn't exist.";
64
65   HardwareDisplayController* controller = *it;
66   controller = *it;
67   // If nothing changed just enable the controller. Note, we perform an exact
68   // comparison on the mode since the refresh rate may have changed.
69   if (SameMode(mode, controller->get_mode()) &&
70       origin == controller->origin() && !controller->IsDisabled())
71     return controller->Enable();
72
73   // Either the mode or the location of the display changed, so exit mirror
74   // mode and configure the display independently. If the caller still wants
75   // mirror mode, subsequent calls configuring the other controllers will
76   // restore mirror mode.
77   if (controller->IsMirrored()) {
78     controller = new HardwareDisplayController(controller->RemoveCrtc(crtc));
79     controllers_.push_back(controller);
80     it = controllers_.end() - 1;
81   }
82
83   HardwareDisplayControllers::iterator mirror =
84       FindActiveDisplayControllerByLocation(modeset_bounds);
85   // Handle mirror mode.
86   if (mirror != controllers_.end() && it != mirror)
87     return HandleMirrorMode(it, mirror, crtc, connector);
88
89   return ModesetDisplayController(controller, origin, mode);
90 }
91
92 bool ScreenManager::DisableDisplayController(uint32_t crtc) {
93   HardwareDisplayControllers::iterator it = FindDisplayController(crtc);
94   if (it != controllers_.end()) {
95     if ((*it)->IsMirrored()) {
96       HardwareDisplayController* controller =
97           new HardwareDisplayController((*it)->RemoveCrtc(crtc));
98       controllers_.push_back(controller);
99     }
100
101     (*it)->Disable();
102     return true;
103   }
104
105   LOG(ERROR) << "Failed to find display controller crtc=" << crtc;
106   return false;
107 }
108
109 base::WeakPtr<HardwareDisplayController> ScreenManager::GetDisplayController(
110     const gfx::Rect& bounds) {
111   // TODO(dnicoara): Remove hack once TestScreen uses a simple Ozone display
112   // configuration reader and ScreenManager is called from there to create the
113   // one display needed by the content_shell target.
114   if (controllers_.empty())
115     ForceInitializationOfPrimaryDisplay();
116
117   HardwareDisplayControllers::iterator it =
118       FindActiveDisplayControllerByLocation(bounds);
119   if (it != controllers_.end())
120     return (*it)->AsWeakPtr();
121
122   return base::WeakPtr<HardwareDisplayController>();
123 }
124
125 ScreenManager::HardwareDisplayControllers::iterator
126 ScreenManager::FindDisplayController(uint32_t crtc) {
127   for (HardwareDisplayControllers::iterator it = controllers_.begin();
128        it != controllers_.end();
129        ++it) {
130     if ((*it)->HasCrtc(crtc))
131       return it;
132   }
133
134   return controllers_.end();
135 }
136
137 ScreenManager::HardwareDisplayControllers::iterator
138 ScreenManager::FindActiveDisplayControllerByLocation(const gfx::Rect& bounds) {
139   for (HardwareDisplayControllers::iterator it = controllers_.begin();
140        it != controllers_.end();
141        ++it) {
142     gfx::Rect controller_bounds((*it)->origin(), (*it)->GetModeSize());
143     // We don't perform a strict check since content_shell will have windows
144     // smaller than the display size.
145     if (controller_bounds.Contains(bounds) && !(*it)->IsDisabled())
146       return it;
147   }
148
149   return controllers_.end();
150 }
151
152 void ScreenManager::ForceInitializationOfPrimaryDisplay() {
153   LOG(WARNING) << "Forcing initialization of primary display.";
154   ScopedVector<HardwareDisplayControllerInfo> displays =
155       GetAvailableDisplayControllerInfos(dri_->get_fd());
156
157   if (displays.empty())
158     return;
159
160   ScopedDrmPropertyPtr dpms(
161       dri_->GetProperty(displays[0]->connector(), "DPMS"));
162   if (dpms)
163     dri_->SetProperty(displays[0]->connector()->connector_id,
164                       dpms->prop_id,
165                       DRM_MODE_DPMS_ON);
166
167   AddDisplayController(dri_, displays[0]->crtc()->crtc_id,
168                        displays[0]->connector()->connector_id);
169   ConfigureDisplayController(displays[0]->crtc()->crtc_id,
170                              displays[0]->connector()->connector_id,
171                              gfx::Point(),
172                              displays[0]->connector()->modes[0]);
173 }
174
175 bool ScreenManager::ModesetDisplayController(
176     HardwareDisplayController* controller,
177     const gfx::Point& origin,
178     const drmModeModeInfo& mode) {
179   controller->set_origin(origin);
180   // Create a surface suitable for the current controller.
181   scoped_refptr<ScanoutBuffer> buffer =
182       buffer_generator_->Create(gfx::Size(mode.hdisplay, mode.vdisplay));
183
184   if (!buffer.get()) {
185     LOG(ERROR) << "Failed to create scanout buffer";
186     return false;
187   }
188
189   if (!controller->Modeset(OverlayPlane(buffer), mode)) {
190     LOG(ERROR) << "Failed to modeset controller";
191     return false;
192   }
193
194   return true;
195 }
196
197 bool ScreenManager::HandleMirrorMode(
198     HardwareDisplayControllers::iterator original,
199     HardwareDisplayControllers::iterator mirror,
200     uint32_t crtc,
201     uint32_t connector) {
202   (*mirror)->AddCrtc((*original)->RemoveCrtc(crtc));
203   if ((*mirror)->Enable()) {
204     controllers_.erase(original);
205     return true;
206   }
207
208   LOG(ERROR) << "Failed to switch to mirror mode";
209
210   // When things go wrong revert back to the previous configuration since
211   // it is expected that the configuration would not have changed if
212   // things fail.
213   (*original)->AddCrtc((*mirror)->RemoveCrtc(crtc));
214   (*original)->Enable();
215   return false;
216 }
217
218 }  // namespace ui