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/chromeos/display_message_handler.h"
6
7#include "ui/display/types/display_mode.h"
8#include "ui/display/types/display_snapshot.h"
9#include "ui/ozone/common/chromeos/display_util.h"
10#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
11#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
12#include "ui/ozone/platform/dri/chromeos/native_display_delegate_dri.h"
13
14namespace ui {
15
16namespace {
17
18class FindDisplayById {
19 public:
20  FindDisplayById(int64_t display_id) : display_id_(display_id) {}
21
22  bool operator()(const DisplaySnapshot_Params& display) const {
23    return display.display_id == display_id_;
24  }
25
26 private:
27  int64_t display_id_;
28};
29
30}  // namespace
31
32DisplayMessageHandler::DisplayMessageHandler(
33    scoped_ptr<NativeDisplayDelegateDri> ndd)
34    : sender_(NULL),
35      ndd_(ndd.Pass()) {}
36
37DisplayMessageHandler::~DisplayMessageHandler() {}
38
39void DisplayMessageHandler::OnChannelEstablished(IPC::Sender* sender) {
40  sender_ = sender;
41}
42
43bool DisplayMessageHandler::OnMessageReceived(const IPC::Message& message) {
44  bool handled = true;
45
46  IPC_BEGIN_MESSAGE_MAP(DisplayMessageHandler, message)
47  IPC_MESSAGE_HANDLER(OzoneGpuMsg_ForceDPMSOn, OnForceDPMSOn)
48  IPC_MESSAGE_HANDLER(OzoneGpuMsg_RefreshNativeDisplays,
49                      OnRefreshNativeDisplays)
50  IPC_MESSAGE_HANDLER(OzoneGpuMsg_ConfigureNativeDisplay,
51                      OnConfigureNativeDisplay)
52  IPC_MESSAGE_HANDLER(OzoneGpuMsg_DisableNativeDisplay,
53                      OnDisableNativeDisplay)
54  IPC_MESSAGE_UNHANDLED(handled = false);
55  IPC_END_MESSAGE_MAP()
56
57  return handled;
58}
59
60void DisplayMessageHandler::OnForceDPMSOn() {
61  ndd_->ForceDPMSOn();
62}
63
64void DisplayMessageHandler::OnRefreshNativeDisplays(
65    const std::vector<DisplaySnapshot_Params>& cached_displays) {
66  std::vector<DisplaySnapshot_Params> displays;
67  std::vector<DisplaySnapshot*> native_displays = ndd_->GetDisplays();
68
69  // If any of the cached displays are in the list of new displays then apply
70  // their configuration immediately.
71  for (size_t i = 0; i < native_displays.size(); ++i) {
72    std::vector<DisplaySnapshot_Params>::const_iterator it =
73        std::find_if(cached_displays.begin(),
74                     cached_displays.end(),
75                     FindDisplayById(native_displays[i]->display_id()));
76
77    if (it == cached_displays.end())
78      continue;
79
80    if (it->has_current_mode)
81      OnConfigureNativeDisplay(it->display_id, it->current_mode, it->origin);
82    else
83      OnDisableNativeDisplay(it->display_id);
84  }
85
86  for (size_t i = 0; i < native_displays.size(); ++i)
87    displays.push_back(GetDisplaySnapshotParams(*native_displays[i]));
88
89  sender_->Send(new OzoneHostMsg_UpdateNativeDisplays(displays));
90}
91
92void DisplayMessageHandler::OnConfigureNativeDisplay(
93    int64_t id,
94    const DisplayMode_Params& mode_param,
95    const gfx::Point& origin) {
96  DisplaySnapshot* display = ndd_->FindDisplaySnapshot(id);
97  if (!display) {
98    LOG(ERROR) << "There is no display with ID " << id;
99    return;
100  }
101
102  const DisplayMode* mode = NULL;
103  for (size_t i = 0; i < display->modes().size(); ++i) {
104    if (mode_param.size == display->modes()[i]->size() &&
105        mode_param.is_interlaced == display->modes()[i]->is_interlaced() &&
106        mode_param.refresh_rate == display->modes()[i]->refresh_rate()) {
107      mode = display->modes()[i];
108      break;
109    }
110  }
111
112  // If the display doesn't have the mode natively, then lookup the mode from
113  // other displays and try using it on the current display (some displays
114  // support panel fitting and they can use different modes even if the mode
115  // isn't explicitly declared).
116  if (!mode)
117    mode = ndd_->FindDisplayMode(mode_param.size,
118                                 mode_param.is_interlaced,
119                                 mode_param.refresh_rate);
120
121  if (!mode) {
122    LOG(ERROR) << "Failed to find mode: size=" << mode_param.size.ToString()
123               << " is_interlaced=" << mode_param.is_interlaced
124               << " refresh_rate=" << mode_param.refresh_rate;
125    return;
126  }
127
128  ndd_->Configure(*display, mode, origin);
129}
130
131void DisplayMessageHandler::OnDisableNativeDisplay(int64_t id) {
132  DisplaySnapshot* display = ndd_->FindDisplaySnapshot(id);
133  if (display)
134    ndd_->Configure(*display, NULL, gfx::Point());
135  else
136    LOG(ERROR) << "There is no display with ID " << id;
137}
138
139}  // namespace ui
140