Fix search results being clipped in app list.
[chromium-blink-merge.git] / ui / ozone / platform / drm / host / drm_native_display_delegate.cc
blobc9054241de7e460e5864d703575d04febe468c62
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 #include "ui/ozone/platform/drm/host/drm_native_display_delegate.h"
7 #include <stdio.h>
9 #include "base/logging.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "base/threading/worker_pool.h"
13 #include "ui/display/types/display_snapshot.h"
14 #include "ui/display/types/native_display_observer.h"
15 #include "ui/events/ozone/device/device_event.h"
16 #include "ui/events/ozone/device/device_manager.h"
17 #include "ui/ozone/common/display_snapshot_proxy.h"
18 #include "ui/ozone/common/display_util.h"
19 #include "ui/ozone/common/gpu/ozone_gpu_messages.h"
20 #include "ui/ozone/platform/drm/host/display_manager.h"
21 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
23 namespace ui {
25 namespace {
27 typedef base::Callback<void(const base::FilePath&, base::File)>
28 OnOpenDeviceReplyCallback;
30 void OpenDeviceOnWorkerThread(
31 const base::FilePath& path,
32 const scoped_refptr<base::TaskRunner>& reply_runner,
33 const OnOpenDeviceReplyCallback& callback) {
34 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
35 base::File::FLAG_WRITE);
37 base::File::Info info;
38 file.GetInfo(&info);
40 CHECK(!info.is_directory);
41 CHECK(path.DirName() == base::FilePath("/dev/dri"));
43 if (file.IsValid()) {
44 reply_runner->PostTask(
45 FROM_HERE, base::Bind(callback, path, base::Passed(file.Pass())));
49 class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy {
50 public:
51 DrmDisplaySnapshotProxy(const DisplaySnapshot_Params& params,
52 DisplayManager* display_manager)
53 : DisplaySnapshotProxy(params), display_manager_(display_manager) {
54 display_manager_->RegisterDisplay(this);
57 ~DrmDisplaySnapshotProxy() override {
58 display_manager_->UnregisterDisplay(this);
61 private:
62 DisplayManager* display_manager_; // Not owned.
64 DISALLOW_COPY_AND_ASSIGN(DrmDisplaySnapshotProxy);
67 } // namespace
69 DrmNativeDisplayDelegate::DrmNativeDisplayDelegate(
70 DrmGpuPlatformSupportHost* proxy,
71 DeviceManager* device_manager,
72 DisplayManager* display_manager,
73 const base::FilePath& primary_graphics_card_path)
74 : proxy_(proxy),
75 device_manager_(device_manager),
76 display_manager_(display_manager),
77 primary_graphics_card_path_(primary_graphics_card_path),
78 has_dummy_display_(false),
79 weak_ptr_factory_(this) {
80 proxy_->RegisterHandler(this);
83 DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() {
84 device_manager_->RemoveObserver(this);
85 proxy_->UnregisterHandler(this);
88 void DrmNativeDisplayDelegate::Initialize() {
89 device_manager_->AddObserver(this);
90 device_manager_->ScanDevices(this);
92 if (!displays_.empty())
93 return;
94 DisplaySnapshot_Params params;
95 bool success = false;
97 // The file generated by frecon that contains EDID for the 1st display.
98 const base::FilePath kEDIDFile("/tmp/display_info.bin");
100 // Just read it on current thread as this is necessary information
101 // to start. This access only tmpfs, which is fast.
102 // TODO(dnicoara|oshima): crbug.com/450886.
103 base::ThreadRestrictions::ScopedAllowIO allow_io;
104 success = CreateSnapshotFromEDIDFile(kEDIDFile, &params);
107 // Fallback to command line if the file doesn't exit or failed to read.
108 if (success || CreateSnapshotFromCommandLine(&params)) {
109 LOG_IF(ERROR, !success) << "Failed to read display_info.bin.";
110 DCHECK_NE(DISPLAY_CONNECTION_TYPE_NONE, params.type);
111 displays_.push_back(new DrmDisplaySnapshotProxy(params, display_manager_));
112 has_dummy_display_ = true;
113 } else {
114 LOG(ERROR) << "Failed to obtain initial display info";
118 void DrmNativeDisplayDelegate::GrabServer() {
121 void DrmNativeDisplayDelegate::UngrabServer() {
124 bool DrmNativeDisplayDelegate::TakeDisplayControl() {
125 proxy_->Send(new OzoneGpuMsg_TakeDisplayControl());
126 return true;
129 bool DrmNativeDisplayDelegate::RelinquishDisplayControl() {
130 proxy_->Send(new OzoneGpuMsg_RelinquishDisplayControl());
131 return true;
134 void DrmNativeDisplayDelegate::SyncWithServer() {
137 void DrmNativeDisplayDelegate::SetBackgroundColor(uint32_t color_argb) {
138 NOTIMPLEMENTED();
141 void DrmNativeDisplayDelegate::ForceDPMSOn() {
144 void DrmNativeDisplayDelegate::GetDisplays(
145 const GetDisplaysCallback& callback) {
146 get_displays_callback_ = callback;
147 // GetDisplays() is supposed to force a refresh of the display list.
148 if (!proxy_->Send(new OzoneGpuMsg_RefreshNativeDisplays())) {
149 get_displays_callback_.Reset();
150 callback.Run(displays_.get());
154 void DrmNativeDisplayDelegate::AddMode(const DisplaySnapshot& output,
155 const DisplayMode* mode) {
158 void DrmNativeDisplayDelegate::Configure(const DisplaySnapshot& output,
159 const DisplayMode* mode,
160 const gfx::Point& origin,
161 const ConfigureCallback& callback) {
162 // The dummy display is used on the first run only. Note: cannot post a task
163 // here since there is no task runner.
164 if (has_dummy_display_) {
165 callback.Run(true);
166 return;
169 configure_callback_map_[output.display_id()] = callback;
171 bool status = false;
172 if (mode) {
173 status = proxy_->Send(new OzoneGpuMsg_ConfigureNativeDisplay(
174 output.display_id(), GetDisplayModeParams(*mode), origin));
175 } else {
176 status =
177 proxy_->Send(new OzoneGpuMsg_DisableNativeDisplay(output.display_id()));
180 if (!status)
181 OnDisplayConfigured(output.display_id(), false);
184 void DrmNativeDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) {
187 bool DrmNativeDisplayDelegate::GetHDCPState(const DisplaySnapshot& output,
188 HDCPState* state) {
189 NOTIMPLEMENTED();
190 return false;
193 bool DrmNativeDisplayDelegate::SetHDCPState(const DisplaySnapshot& output,
194 HDCPState state) {
195 NOTIMPLEMENTED();
196 return false;
199 std::vector<ColorCalibrationProfile>
200 DrmNativeDisplayDelegate::GetAvailableColorCalibrationProfiles(
201 const DisplaySnapshot& output) {
202 NOTIMPLEMENTED();
203 return std::vector<ColorCalibrationProfile>();
206 bool DrmNativeDisplayDelegate::SetColorCalibrationProfile(
207 const DisplaySnapshot& output,
208 ColorCalibrationProfile new_profile) {
209 NOTIMPLEMENTED();
210 return false;
213 void DrmNativeDisplayDelegate::AddObserver(NativeDisplayObserver* observer) {
214 observers_.AddObserver(observer);
217 void DrmNativeDisplayDelegate::RemoveObserver(NativeDisplayObserver* observer) {
218 observers_.RemoveObserver(observer);
221 void DrmNativeDisplayDelegate::OnDeviceEvent(const DeviceEvent& event) {
222 if (event.device_type() != DeviceEvent::DISPLAY)
223 return;
225 switch (event.action_type()) {
226 case DeviceEvent::ADD:
227 VLOG(1) << "Got display added event for " << event.path().value();
228 // The default card is a special case since it needs to be opened early on
229 // the GPU process in order to initialize EGL. If it is opened here as
230 // well, it will cause a race with opening it in the GPU process and the
231 // GPU process may fail initialization.
232 // TODO(dnicoara) Remove this when the media stack does not require super
233 // early initialization.
234 if (event.path() == primary_graphics_card_path_)
235 return;
237 base::WorkerPool::PostTask(
238 FROM_HERE,
239 base::Bind(&OpenDeviceOnWorkerThread, event.path(),
240 base::ThreadTaskRunnerHandle::Get(),
241 base::Bind(&DrmNativeDisplayDelegate::OnNewGraphicsDevice,
242 weak_ptr_factory_.GetWeakPtr())),
243 false /* task_is_slow */);
244 return;
245 case DeviceEvent::CHANGE:
246 VLOG(1) << "Got display changed event for " << event.path().value();
247 break;
248 case DeviceEvent::REMOVE:
249 VLOG(1) << "Got display removed event for " << event.path().value();
250 // It shouldn't be possible to remove this device.
251 DCHECK(primary_graphics_card_path_ != event.path())
252 << "Got event to remove primary graphics card "
253 << event.path().value();
254 proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(event.path()));
255 break;
258 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
259 OnConfigurationChanged());
262 void DrmNativeDisplayDelegate::OnNewGraphicsDevice(const base::FilePath& path,
263 base::File file) {
264 DCHECK(file.IsValid());
265 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(
266 path, base::FileDescriptor(file.Pass())));
268 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
269 OnConfigurationChanged());
272 void DrmNativeDisplayDelegate::OnChannelEstablished(
273 int host_id,
274 scoped_refptr<base::SingleThreadTaskRunner> send_runner,
275 const base::Callback<void(IPC::Message*)>& send_callback) {
276 device_manager_->ScanDevices(this);
277 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
278 OnConfigurationChanged());
281 void DrmNativeDisplayDelegate::OnChannelDestroyed(int host_id) {
282 // If the channel got destroyed in the middle of a configuration then just
283 // respond with failure.
284 if (!get_displays_callback_.is_null()) {
285 base::ThreadTaskRunnerHandle::Get()->PostTask(
286 FROM_HERE,
287 base::Bind(&DrmNativeDisplayDelegate::RunUpdateDisplaysCallback,
288 weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
289 get_displays_callback_.Reset();
292 for (const auto& pair : configure_callback_map_) {
293 base::ThreadTaskRunnerHandle::Get()->PostTask(
294 FROM_HERE, base::Bind(pair.second, false));
296 configure_callback_map_.clear();
299 bool DrmNativeDisplayDelegate::OnMessageReceived(const IPC::Message& message) {
300 bool handled = true;
302 IPC_BEGIN_MESSAGE_MAP(DrmNativeDisplayDelegate, message)
303 IPC_MESSAGE_HANDLER(OzoneHostMsg_UpdateNativeDisplays, OnUpdateNativeDisplays)
304 IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayConfigured, OnDisplayConfigured)
305 IPC_MESSAGE_UNHANDLED(handled = false)
306 IPC_END_MESSAGE_MAP()
308 return handled;
311 void DrmNativeDisplayDelegate::OnUpdateNativeDisplays(
312 const std::vector<DisplaySnapshot_Params>& displays) {
313 has_dummy_display_ = false;
314 displays_.clear();
315 for (size_t i = 0; i < displays.size(); ++i)
316 displays_.push_back(
317 new DrmDisplaySnapshotProxy(displays[i], display_manager_));
319 if (!get_displays_callback_.is_null()) {
320 base::ThreadTaskRunnerHandle::Get()->PostTask(
321 FROM_HERE,
322 base::Bind(&DrmNativeDisplayDelegate::RunUpdateDisplaysCallback,
323 weak_ptr_factory_.GetWeakPtr(), get_displays_callback_));
324 get_displays_callback_.Reset();
328 void DrmNativeDisplayDelegate::OnDisplayConfigured(int64_t display_id,
329 bool status) {
330 auto it = configure_callback_map_.find(display_id);
331 if (it != configure_callback_map_.end()) {
332 base::ThreadTaskRunnerHandle::Get()->PostTask(
333 FROM_HERE, base::Bind(it->second, status));
334 configure_callback_map_.erase(it);
338 void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback(
339 const GetDisplaysCallback& callback) const {
340 callback.Run(displays_.get());
343 } // namespace ui