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