blob: 24657b41911b4d54d103faa9ba064d10e7ed98ab [file] [log] [blame]
dnicoara9372a7912014-12-11 01:29:061// 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
kylechar731f85f92016-12-01 20:50:465#include "ui/display/manager/chromeos/configure_displays_task.h"
dnicoara9372a7912014-12-11 01:29:066
7#include "base/auto_reset.h"
8#include "base/bind.h"
kylechar731f85f92016-12-01 20:50:469#include "ui/display/manager/chromeos/display_util.h"
dnicoara9372a7912014-12-11 01:29:0610#include "ui/display/types/display_snapshot.h"
11#include "ui/display/types/native_display_delegate.h"
12
13namespace ui {
14
15namespace {
16
17// Find the next best mode after |display_mode|. If none can be found return
18// nullptr.
19const DisplayMode* FindNextMode(const DisplaySnapshot& display_state,
dnicoaraa89c2082015-01-05 16:49:0620 const DisplayMode* display_mode) {
21 if (!display_mode)
22 return nullptr;
23
dnicoara9372a7912014-12-11 01:29:0624 int best_mode_pixels = 0;
25 const DisplayMode* best_mode = nullptr;
dnicoaraa89c2082015-01-05 16:49:0626 int current_mode_pixels = display_mode->size().GetArea();
dbasehore01e90042016-05-27 06:16:5127 for (const std::unique_ptr<const DisplayMode>& mode : display_state.modes()) {
dnicoara9372a7912014-12-11 01:29:0628 int pixel_count = mode->size().GetArea();
29 if (pixel_count < current_mode_pixels && pixel_count > best_mode_pixels) {
dbasehore01e90042016-05-27 06:16:5130 best_mode = mode.get();
dnicoara9372a7912014-12-11 01:29:0631 best_mode_pixels = pixel_count;
32 }
33 }
34
35 return best_mode;
36}
37
38} // namespace
39
40DisplayConfigureRequest::DisplayConfigureRequest(DisplaySnapshot* display,
41 const DisplayMode* mode,
42 const gfx::Point& origin)
kylechar731f85f92016-12-01 20:50:4643 : display(display), mode(mode), origin(origin) {}
dnicoara9372a7912014-12-11 01:29:0644
45ConfigureDisplaysTask::ConfigureDisplaysTask(
46 NativeDisplayDelegate* delegate,
47 const std::vector<DisplayConfigureRequest>& requests,
48 const ResponseCallback& callback)
49 : delegate_(delegate),
50 requests_(requests),
51 callback_(callback),
52 is_configuring_(false),
53 num_displays_configured_(0),
54 task_status_(SUCCESS),
55 weak_ptr_factory_(this) {
56 for (size_t i = 0; i < requests_.size(); ++i)
57 pending_request_indexes_.push(i);
58}
59
kylechar731f85f92016-12-01 20:50:4660ConfigureDisplaysTask::~ConfigureDisplaysTask() {}
dnicoara9372a7912014-12-11 01:29:0661
62void ConfigureDisplaysTask::Run() {
63 // Synchronous configurators will recursively call Run(). In that case just
64 // defer their call to the next iteration in the while-loop. This is done to
65 // guard against stack overflows if the display has a large list of broken
66 // modes.
67 if (is_configuring_)
68 return;
69
dnicoara65d9d312014-12-13 02:30:4770 {
71 base::AutoReset<bool> recursivity_guard(&is_configuring_, true);
72 while (!pending_request_indexes_.empty()) {
73 size_t index = pending_request_indexes_.front();
74 DisplayConfigureRequest* request = &requests_[index];
75 pending_request_indexes_.pop();
robert.bradford3d88a672015-12-10 11:51:3876 // Non-native displays do not require configuration through the
77 // NativeDisplayDelegate.
78 if (!IsPhysicalDisplayType(request->display->type())) {
79 OnConfigured(index, true);
80 } else {
81 delegate_->Configure(*request->display, request->mode, request->origin,
82 base::Bind(&ConfigureDisplaysTask::OnConfigured,
83 weak_ptr_factory_.GetWeakPtr(), index));
84 }
dnicoara65d9d312014-12-13 02:30:4785 }
dnicoara9372a7912014-12-11 01:29:0686 }
87
dnicoara65d9d312014-12-13 02:30:4788 // Nothing should be modified after the |callback_| is called since the
dnicoara9372a7912014-12-11 01:29:0689 // task may be deleted in the callback.
90 if (num_displays_configured_ == requests_.size())
91 callback_.Run(task_status_);
92}
93
94void ConfigureDisplaysTask::OnConfigured(size_t index, bool success) {
95 DisplayConfigureRequest* request = &requests_[index];
96 VLOG(2) << "Configured status=" << success
97 << " display=" << request->display->display_id()
98 << " origin=" << request->origin.ToString()
99 << " mode=" << (request->mode ? request->mode->ToString() : "null");
100 if (!success) {
dnicoaraa89c2082015-01-05 16:49:06101 request->mode = FindNextMode(*request->display, request->mode);
dnicoara9372a7912014-12-11 01:29:06102 if (request->mode) {
103 pending_request_indexes_.push(index);
104 if (task_status_ == SUCCESS)
105 task_status_ = PARTIAL_SUCCESS;
106
107 Run();
108 return;
109 }
110 } else {
111 request->display->set_current_mode(request->mode);
112 request->display->set_origin(request->origin);
113 }
114
115 num_displays_configured_++;
116 if (!success)
117 task_status_ = ERROR;
118
119 Run();
120}
121
122} // namespace ui