Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: chromeos/display/real_output_configurator_delegate.cc

Issue 22871010: chromeos: Include mode details in OutputSnapshot. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add out-of-line dtor for OutputSnapshot Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/display/real_output_configurator_delegate.h" 5 #include "chromeos/display/real_output_configurator_delegate.h"
6 6
7 #include <X11/Xatom.h> 7 #include <X11/Xatom.h>
8 #include <X11/Xlib.h> 8 #include <X11/Xlib.h>
9 #include <X11/extensions/dpms.h> 9 #include <X11/extensions/dpms.h>
10 #include <X11/extensions/XInput.h> 10 #include <X11/extensions/XInput.h>
11 #include <X11/extensions/XInput2.h> 11 #include <X11/extensions/XInput2.h>
12 #include <X11/extensions/Xrandr.h> 12 #include <X11/extensions/Xrandr.h>
13 13
14 #include <cmath> 14 #include <cmath>
15 #include <utility>
15 16
16 #include "base/logging.h" 17 #include "base/logging.h"
17 #include "base/message_loop/message_pump_aurax11.h" 18 #include "base/message_loop/message_pump_aurax11.h"
18 #include "chromeos/dbus/dbus_thread_manager.h" 19 #include "chromeos/dbus/dbus_thread_manager.h"
19 #include "chromeos/dbus/power_manager_client.h" 20 #include "chromeos/dbus/power_manager_client.h"
20 #include "chromeos/display/output_util.h" 21 #include "chromeos/display/output_util.h"
21 22
22 namespace chromeos { 23 namespace chromeos {
23 24
24 namespace { 25 namespace {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 RealOutputConfiguratorDelegate::GetOutputs( 109 RealOutputConfiguratorDelegate::GetOutputs(
109 const OutputConfigurator::StateController* state_controller) { 110 const OutputConfigurator::StateController* state_controller) {
110 CHECK(screen_) << "Server not grabbed"; 111 CHECK(screen_) << "Server not grabbed";
111 112
112 std::vector<OutputConfigurator::OutputSnapshot> outputs; 113 std::vector<OutputConfigurator::OutputSnapshot> outputs;
113 XRROutputInfo* one_info = NULL; 114 XRROutputInfo* one_info = NULL;
114 XRROutputInfo* two_info = NULL; 115 XRROutputInfo* two_info = NULL;
115 RRCrtc last_used_crtc = None; 116 RRCrtc last_used_crtc = None;
116 117
117 for (int i = 0; i < screen_->noutput && outputs.size() < 2; ++i) { 118 for (int i = 0; i < screen_->noutput && outputs.size() < 2; ++i) {
118 RROutput this_id = screen_->outputs[i]; 119 RROutput output_id = screen_->outputs[i];
119 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, this_id); 120 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id);
120 bool is_connected = (output_info->connection == RR_Connected); 121 bool is_connected = (output_info->connection == RR_Connected);
121 122
122 if (is_connected) { 123 if (!is_connected) {
123 OutputConfigurator::OutputSnapshot to_populate; 124 XRRFreeOutputInfo(output_info);
124 to_populate.output = this_id; 125 continue;
125 to_populate.has_display_id = 126 }
126 GetDisplayId(this_id, i, &to_populate.display_id);
127 to_populate.is_internal = IsInternalOutput(output_info);
128 // Use the index as a valid display id even if the internal
129 // display doesn't have valid EDID because the index
130 // will never change.
131 if (!to_populate.has_display_id && to_populate.is_internal)
132 to_populate.has_display_id = true;
133 127
134 (outputs.empty() ? one_info : two_info) = output_info; 128 OutputConfigurator::OutputSnapshot output;
oshima 2013/08/15 19:03:24 Consider moving the creation to separate method as
Daniel Erat 2013/08/15 19:26:23 I'm worried that that would make the code more com
oshima 2013/08/15 19:37:26 It looked to me that you can create from three par
Daniel Erat 2013/08/15 21:20:33 It takes few more than that (to initialize all of
129 output.output = output_id;
130 output.width_mm = output_info->mm_width;
131 output.height_mm = output_info->mm_height;
132 output.has_display_id = GetDisplayId(output_id, i, &output.display_id);
133 output.is_internal = IsInternalOutput(output_info);
134 // Use the index as a valid display id even if the internal
135 // display doesn't have valid EDID because the index
136 // will never change.
137 if (!output.has_display_id && output.is_internal)
138 output.has_display_id = true;
135 139
136 // Now, look up the current CRTC and any related info. 140 (outputs.empty() ? one_info : two_info) = output_info;
137 if (output_info->crtc) { 141
138 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo( 142 // Now, look up the current CRTC and any related info.
139 display_, screen_, output_info->crtc); 143 if (output_info->crtc) {
140 to_populate.current_mode = crtc_info->mode; 144 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(
141 to_populate.x = crtc_info->x; 145 display_, screen_, output_info->crtc);
142 to_populate.y = crtc_info->y; 146 output.current_mode = crtc_info->mode;
143 XRRFreeCrtcInfo(crtc_info); 147 output.x = crtc_info->x;
148 output.y = crtc_info->y;
149 XRRFreeCrtcInfo(crtc_info);
150 }
151
152 // Assign a CRTC that isn't already in use.
153 for (int j = 0; j < output_info->ncrtc; ++j) {
154 if (output_info->crtcs[j] != last_used_crtc) {
155 output.crtc = output_info->crtcs[j];
156 last_used_crtc = output.crtc;
157 break;
144 } 158 }
159 }
145 160
146 // Assign a CRTC that isn't already in use. 161 output.native_mode = GetOutputNativeMode(output_info);
147 for (int j = 0; j < output_info->ncrtc; ++j) { 162
148 if (output_info->crtcs[j] != last_used_crtc) { 163 if (output.has_display_id) {
149 to_populate.crtc = output_info->crtcs[j]; 164 int width = 0, height = 0;
150 last_used_crtc = to_populate.crtc; 165 if (state_controller &&
151 break; 166 state_controller->GetResolutionForDisplayId(
152 } 167 output.display_id, &width, &height)) {
168 output.selected_mode =
169 FindOutputModeMatchingSize(screen_, output_info, width, height);
153 } 170 }
154 to_populate.native_mode = GetOutputNativeMode(output_info); 171 }
155 if (to_populate.has_display_id) { 172 // Fall back to native mode.
156 int width = 0, height = 0; 173 if (output.selected_mode == None)
157 if (state_controller && 174 output.selected_mode = output.native_mode;
158 state_controller->GetResolutionForDisplayId(
159 to_populate.display_id, &width, &height)) {
160 to_populate.selected_mode =
161 FindOutputModeMatchingSize(screen_, output_info, width, height);
162 }
163 }
164 // Fallback to native mode.
165 if (to_populate.selected_mode == None)
166 to_populate.selected_mode = to_populate.native_mode;
167 175
168 to_populate.is_aspect_preserving_scaling = 176 output.is_aspect_preserving_scaling =
169 IsOutputAspectPreservingScaling(this_id); 177 IsOutputAspectPreservingScaling(output_id);
170 to_populate.touch_device_id = None; 178 output.touch_device_id = None;
171 179
172 VLOG(2) << "Found display " << outputs.size() << ":" 180 for (int mode_index = 0; mode_index < output_info->nmode; ++mode_index) {
173 << " output=" << to_populate.output 181 const RRMode mode = output_info->modes[mode_index];
174 << " crtc=" << to_populate.crtc 182 OutputConfigurator::ModeInfo info;
175 << " current_mode=" << to_populate.current_mode; 183 if (GetModeDetails(mode, &info.width, &info.height, &info.interlaced))
176 outputs.push_back(to_populate); 184 output.mode_infos.insert(std::make_pair(mode, info));
177 } else { 185 else
178 XRRFreeOutputInfo(output_info); 186 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
179 } 187 }
188
189 VLOG(2) << "Found display " << outputs.size() << ":"
190 << " output=" << output.output
191 << " crtc=" << output.crtc
192 << " current_mode=" << output.current_mode;
193 outputs.push_back(output);
180 } 194 }
181 195
182 if (outputs.size() == 2) { 196 if (outputs.size() == 2) {
183 bool one_is_internal = IsInternalOutput(one_info); 197 bool one_is_internal = IsInternalOutput(one_info);
184 bool two_is_internal = IsInternalOutput(two_info); 198 bool two_is_internal = IsInternalOutput(two_info);
185 int internal_outputs = (one_is_internal ? 1 : 0) + 199 int internal_outputs = (one_is_internal ? 1 : 0) +
186 (two_is_internal ? 1 : 0); 200 (two_is_internal ? 1 : 0);
187 DCHECK_LT(internal_outputs, 2); 201 DCHECK_LT(internal_outputs, 2);
188 LOG_IF(WARNING, internal_outputs == 2) 202 LOG_IF(WARNING, internal_outputs == 2)
189 << "Two internal outputs detected."; 203 << "Two internal outputs detected.";
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 } 235 }
222 } 236 }
223 } 237 }
224 238
225 GetTouchscreens(&outputs); 239 GetTouchscreens(&outputs);
226 XRRFreeOutputInfo(one_info); 240 XRRFreeOutputInfo(one_info);
227 XRRFreeOutputInfo(two_info); 241 XRRFreeOutputInfo(two_info);
228 return outputs; 242 return outputs;
229 } 243 }
230 244
231 bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
232 int* width,
233 int* height,
234 bool* interlaced) {
235 CHECK(screen_) << "Server not grabbed";
236 // TODO: Determine if we need to organize modes in a way which provides
237 // better than O(n) lookup time. In many call sites, for example, the
238 // "next" mode is typically what we are looking for so using this
239 // helper might be too expensive.
240 for (int i = 0; i < screen_->nmode; ++i) {
241 if (mode == screen_->modes[i].id) {
242 const XRRModeInfo& info = screen_->modes[i];
243 if (width)
244 *width = info.width;
245 if (height)
246 *height = info.height;
247 if (interlaced)
248 *interlaced = info.modeFlags & RR_Interlace;
249 return true;
250 }
251 }
252 return false;
253 }
254
255 bool RealOutputConfiguratorDelegate::ConfigureCrtc( 245 bool RealOutputConfiguratorDelegate::ConfigureCrtc(
256 RRCrtc crtc, 246 RRCrtc crtc,
257 RRMode mode, 247 RRMode mode,
258 RROutput output, 248 RROutput output,
259 int x, 249 int x,
260 int y) { 250 int y) {
261 CHECK(screen_) << "Server not grabbed"; 251 CHECK(screen_) << "Server not grabbed";
262 VLOG(1) << "ConfigureCrtc: crtc=" << crtc 252 VLOG(1) << "ConfigureCrtc: crtc=" << crtc
263 << " mode=" << mode 253 << " mode=" << mode
264 << " output=" << output 254 << " output=" << output
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 } 326 }
337 XIFreeDeviceInfo(info); 327 XIFreeDeviceInfo(info);
338 } 328 }
339 329
340 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager( 330 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager(
341 bool projecting) { 331 bool projecting) {
342 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 332 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
343 SetIsProjecting(projecting); 333 SetIsProjecting(projecting);
344 } 334 }
345 335
336 bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
337 int* width,
338 int* height,
339 bool* interlaced) {
340 CHECK(screen_) << "Server not grabbed";
341 // TODO: Determine if we need to organize modes in a way which provides
342 // better than O(n) lookup time. In many call sites, for example, the
343 // "next" mode is typically what we are looking for so using this
344 // helper might be too expensive.
345 for (int i = 0; i < screen_->nmode; ++i) {
346 if (mode == screen_->modes[i].id) {
347 const XRRModeInfo& info = screen_->modes[i];
348 if (width)
349 *width = info.width;
350 if (height)
351 *height = info.height;
352 if (interlaced)
353 *interlaced = info.modeFlags & RR_Interlace;
354 return true;
355 }
356 }
357 return false;
358 }
359
346 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( 360 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
347 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { 361 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
348 CHECK(screen_) << "Server not grabbed"; 362 CHECK(screen_) << "Server not grabbed";
349 // Setting the screen size will fail if any CRTC doesn't fit afterwards. 363 // Setting the screen size will fail if any CRTC doesn't fit afterwards.
350 // At the same time, turning CRTCs off and back on uses up a lot of time. 364 // At the same time, turning CRTCs off and back on uses up a lot of time.
351 // This function tries to be smart to avoid too many off/on cycles: 365 // This function tries to be smart to avoid too many off/on cycles:
352 // - We disable all the CRTCs we won't need after the FB resize. 366 // - We disable all the CRTCs we won't need after the FB resize.
353 // - We set the new modes on CRTCs, if they fit in both the old and new 367 // - We set the new modes on CRTCs, if they fit in both the old and new
354 // FBs, and park them at (0,0) 368 // FBs, and park them at (0,0)
355 // - We disable the CRTCs we will need but don't fit in the old FB. Those 369 // - We disable the CRTCs we will need but don't fit in the old FB. Those
356 // will be reenabled after the resize. 370 // will be reenabled after the resize.
357 // We don't worry about the cached state of the outputs here since we are 371 // We don't worry about the cached state of the outputs here since we are
358 // not interested in the state we are setting - we just try to get the CRTCs 372 // not interested in the state we are setting - we just try to get the CRTCs
359 // out of the way so we can rebuild the frame buffer. 373 // out of the way so we can rebuild the frame buffer.
360 for (int i = 0; i < screen_->ncrtc; ++i) { 374 for (int i = 0; i < screen_->ncrtc; ++i) {
361 // Default config is to disable the crtcs. 375 // Default config is to disable the crtcs.
362 RRCrtc crtc = screen_->crtcs[i]; 376 RRCrtc crtc = screen_->crtcs[i];
363 RRMode mode = None; 377 RRMode mode = None;
364 RROutput output = None; 378 RROutput output = None;
379 const OutputConfigurator::ModeInfo* mode_info = NULL;
365 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it = 380 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
366 outputs.begin(); it != outputs.end(); ++it) { 381 outputs.begin(); it != outputs.end(); ++it) {
367 if (crtc == it->crtc) { 382 if (crtc == it->crtc) {
368 mode = it->current_mode; 383 mode = it->current_mode;
369 output = it->output; 384 output = it->output;
385 mode_info = OutputConfigurator::GetModeInfo(*it, mode);
370 break; 386 break;
371 } 387 }
372 } 388 }
373 389
374 if (mode != None) { 390 if (mode_info) {
375 // In case our CRTC doesn't fit in our current framebuffer, disable it. 391 // In case our CRTC doesn't fit in our current framebuffer, disable it.
376 // It'll get reenabled after we resize the framebuffer. 392 // It'll get reenabled after we resize the framebuffer.
377 int mode_width = 0, mode_height = 0;
378 CHECK(GetModeDetails(mode, &mode_width, &mode_height, NULL));
379 int current_width = DisplayWidth(display_, DefaultScreen(display_)); 393 int current_width = DisplayWidth(display_, DefaultScreen(display_));
380 int current_height = DisplayHeight(display_, DefaultScreen(display_)); 394 int current_height = DisplayHeight(display_, DefaultScreen(display_));
381 if (mode_width > current_width || mode_height > current_height) { 395 if (mode_info->width > current_width ||
396 mode_info->height > current_height) {
382 mode = None; 397 mode = None;
383 output = None; 398 output = None;
399 mode_info = NULL;
384 } 400 }
385 } 401 }
386 402
387 ConfigureCrtc(crtc, mode, output, 0, 0); 403 ConfigureCrtc(crtc, mode, output, 0, 0);
388 } 404 }
389 } 405 }
390 406
391 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling( 407 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling(
392 RROutput id) { 408 RROutput id) {
393 bool ret = false; 409 bool ret = false;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 is_direct_touch = touch_info->mode == XIDirectTouch; 563 is_direct_touch = touch_info->mode == XIDirectTouch;
548 } 564 }
549 #endif 565 #endif
550 } 566 }
551 567
552 // Touchscreens should have absolute X and Y axes, 568 // Touchscreens should have absolute X and Y axes,
553 // and be direct touch devices. 569 // and be direct touch devices.
554 if (width > 0.0 && height > 0.0 && is_direct_touch) { 570 if (width > 0.0 && height > 0.0 && is_direct_touch) {
555 size_t k = 0; 571 size_t k = 0;
556 for (; k < outputs->size(); k++) { 572 for (; k < outputs->size(); k++) {
557 if ((*outputs)[k].native_mode == None || 573 OutputConfigurator::OutputSnapshot* output = &(*outputs)[k];
558 (*outputs)[k].touch_device_id != None) 574 if (output->native_mode == None || output->touch_device_id != None)
559 continue; 575 continue;
560 int native_mode_width = 0, native_mode_height = 0; 576
561 if (!GetModeDetails((*outputs)[k].native_mode, &native_mode_width, 577 const OutputConfigurator::ModeInfo* mode_info =
562 &native_mode_height, NULL)) 578 OutputConfigurator::GetModeInfo(*output, output->native_mode);
579 if (!mode_info)
563 continue; 580 continue;
564 581
565 // Allow 1 pixel difference between screen and touchscreen 582 // Allow 1 pixel difference between screen and touchscreen
566 // resolutions. Because in some cases for monitor resolution 583 // resolutions. Because in some cases for monitor resolution
567 // 1024x768 touchscreen's resolution would be 1024x768, but for 584 // 1024x768 touchscreen's resolution would be 1024x768, but for
568 // some 1023x767. It really depends on touchscreen's firmware 585 // some 1023x767. It really depends on touchscreen's firmware
569 // configuration. 586 // configuration.
570 if (std::abs(native_mode_width - width) <= 1.0 && 587 if (std::abs(mode_info->width - width) <= 1.0 &&
571 std::abs(native_mode_height - height) <= 1.0) { 588 std::abs(mode_info->height - height) <= 1.0) {
572 (*outputs)[k].touch_device_id = info[i].deviceid; 589 output->touch_device_id = info[i].deviceid;
573 590
574 VLOG(2) << "Found touchscreen for output #" << k 591 VLOG(2) << "Found touchscreen for output #" << k
575 << " id " << (*outputs)[k].touch_device_id 592 << " id " << output->touch_device_id
576 << " width " << width 593 << " width " << width
577 << " height " << height; 594 << " height " << height;
578 break; 595 break;
579 } 596 }
580 } 597 }
581 598
582 VLOG_IF(2, k == outputs->size()) 599 VLOG_IF(2, k == outputs->size())
583 << "No matching output - ignoring touchscreen" 600 << "No matching output - ignoring touchscreen"
584 << " id " << info[i].deviceid 601 << " id " << info[i].deviceid
585 << " width " << width 602 << " width " << width
586 << " height " << height; 603 << " height " << height;
587 } 604 }
588 } 605 }
589 606
590 XIFreeDeviceInfo(info); 607 XIFreeDeviceInfo(info);
591 } 608 }
592 609
593 } // namespace chromeos 610 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698