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

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: merge 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
« no previous file with comments | « chromeos/display/real_output_configurator_delegate.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <set> 15 #include <set>
16 #include <utility>
16 17
17 #include "base/logging.h" 18 #include "base/logging.h"
18 #include "base/message_loop/message_pump_aurax11.h" 19 #include "base/message_loop/message_pump_aurax11.h"
19 #include "chromeos/dbus/dbus_thread_manager.h" 20 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/power_manager_client.h" 21 #include "chromeos/dbus/power_manager_client.h"
21 #include "chromeos/display/output_util.h" 22 #include "chromeos/display/output_util.h"
22 23
23 namespace chromeos { 24 namespace chromeos {
24 25
25 namespace { 26 namespace {
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 RealOutputConfiguratorDelegate::GetOutputs( 110 RealOutputConfiguratorDelegate::GetOutputs(
110 const OutputConfigurator::StateController* state_controller) { 111 const OutputConfigurator::StateController* state_controller) {
111 CHECK(screen_) << "Server not grabbed"; 112 CHECK(screen_) << "Server not grabbed";
112 113
113 std::vector<OutputConfigurator::OutputSnapshot> outputs; 114 std::vector<OutputConfigurator::OutputSnapshot> outputs;
114 XRROutputInfo* one_info = NULL; 115 XRROutputInfo* one_info = NULL;
115 XRROutputInfo* two_info = NULL; 116 XRROutputInfo* two_info = NULL;
116 RRCrtc last_used_crtc = None; 117 RRCrtc last_used_crtc = None;
117 118
118 for (int i = 0; i < screen_->noutput && outputs.size() < 2; ++i) { 119 for (int i = 0; i < screen_->noutput && outputs.size() < 2; ++i) {
119 RROutput this_id = screen_->outputs[i]; 120 RROutput output_id = screen_->outputs[i];
120 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, this_id); 121 XRROutputInfo* output_info = XRRGetOutputInfo(display_, screen_, output_id);
121 bool is_connected = (output_info->connection == RR_Connected); 122 bool is_connected = (output_info->connection == RR_Connected);
122 123
123 if (is_connected) { 124 if (!is_connected) {
124 OutputConfigurator::OutputSnapshot to_populate; 125 XRRFreeOutputInfo(output_info);
125 to_populate.output = this_id; 126 continue;
126 to_populate.has_display_id = 127 }
127 GetDisplayId(this_id, i, &to_populate.display_id);
128 to_populate.is_internal = IsInternalOutput(output_info);
129 // Use the index as a valid display id even if the internal
130 // display doesn't have valid EDID because the index
131 // will never change.
132 if (!to_populate.has_display_id && to_populate.is_internal)
133 to_populate.has_display_id = true;
134 128
135 (outputs.empty() ? one_info : two_info) = output_info; 129 (outputs.empty() ? one_info : two_info) = output_info;
136 130
137 // Now, look up the current CRTC and any related info. 131 OutputConfigurator::OutputSnapshot output = InitOutputSnapshot(
138 if (output_info->crtc) { 132 output_id, output_info, &last_used_crtc, i);
139 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo( 133
140 display_, screen_, output_info->crtc); 134 if (output.has_display_id) {
141 to_populate.current_mode = crtc_info->mode; 135 int width = 0, height = 0;
142 to_populate.x = crtc_info->x; 136 if (state_controller &&
143 to_populate.y = crtc_info->y; 137 state_controller->GetResolutionForDisplayId(
144 XRRFreeCrtcInfo(crtc_info); 138 output.display_id, &width, &height)) {
139 output.selected_mode =
140 FindOutputModeMatchingSize(screen_, output_info, width, height);
145 } 141 }
142 }
143 // Fall back to native mode.
144 if (output.selected_mode == None)
145 output.selected_mode = output.native_mode;
146 146
147 // Assign a CRTC that isn't already in use. 147 VLOG(2) << "Found display " << outputs.size() << ":"
148 for (int j = 0; j < output_info->ncrtc; ++j) { 148 << " output=" << output.output
149 if (output_info->crtcs[j] != last_used_crtc) { 149 << " crtc=" << output.crtc
150 to_populate.crtc = output_info->crtcs[j]; 150 << " current_mode=" << output.current_mode;
151 last_used_crtc = to_populate.crtc; 151 outputs.push_back(output);
152 break;
153 }
154 }
155 to_populate.native_mode = GetOutputNativeMode(output_info);
156 if (to_populate.has_display_id) {
157 int width = 0, height = 0;
158 if (state_controller &&
159 state_controller->GetResolutionForDisplayId(
160 to_populate.display_id, &width, &height)) {
161 to_populate.selected_mode =
162 FindOutputModeMatchingSize(screen_, output_info, width, height);
163 }
164 }
165 // Fallback to native mode.
166 if (to_populate.selected_mode == None)
167 to_populate.selected_mode = to_populate.native_mode;
168
169 to_populate.is_aspect_preserving_scaling =
170 IsOutputAspectPreservingScaling(this_id);
171 to_populate.touch_device_id = None;
172
173 VLOG(2) << "Found display " << outputs.size() << ":"
174 << " output=" << to_populate.output
175 << " crtc=" << to_populate.crtc
176 << " current_mode=" << to_populate.current_mode;
177 outputs.push_back(to_populate);
178 } else {
179 XRRFreeOutputInfo(output_info);
180 }
181 } 152 }
182 153
183 if (outputs.size() == 2) { 154 if (outputs.size() == 2) {
184 bool one_is_internal = IsInternalOutput(one_info); 155 bool one_is_internal = IsInternalOutput(one_info);
185 bool two_is_internal = IsInternalOutput(two_info); 156 bool two_is_internal = IsInternalOutput(two_info);
186 int internal_outputs = (one_is_internal ? 1 : 0) + 157 int internal_outputs = (one_is_internal ? 1 : 0) +
187 (two_is_internal ? 1 : 0); 158 (two_is_internal ? 1 : 0);
188 DCHECK_LT(internal_outputs, 2); 159 DCHECK_LT(internal_outputs, 2);
189 LOG_IF(WARNING, internal_outputs == 2) 160 LOG_IF(WARNING, internal_outputs == 2)
190 << "Two internal outputs detected."; 161 << "Two internal outputs detected.";
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 } 193 }
223 } 194 }
224 } 195 }
225 196
226 GetTouchscreens(&outputs); 197 GetTouchscreens(&outputs);
227 XRRFreeOutputInfo(one_info); 198 XRRFreeOutputInfo(one_info);
228 XRRFreeOutputInfo(two_info); 199 XRRFreeOutputInfo(two_info);
229 return outputs; 200 return outputs;
230 } 201 }
231 202
232 bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
233 int* width,
234 int* height,
235 bool* interlaced) {
236 CHECK(screen_) << "Server not grabbed";
237 // TODO: Determine if we need to organize modes in a way which provides
238 // better than O(n) lookup time. In many call sites, for example, the
239 // "next" mode is typically what we are looking for so using this
240 // helper might be too expensive.
241 for (int i = 0; i < screen_->nmode; ++i) {
242 if (mode == screen_->modes[i].id) {
243 const XRRModeInfo& info = screen_->modes[i];
244 if (width)
245 *width = info.width;
246 if (height)
247 *height = info.height;
248 if (interlaced)
249 *interlaced = info.modeFlags & RR_Interlace;
250 return true;
251 }
252 }
253 return false;
254 }
255
256 bool RealOutputConfiguratorDelegate::ConfigureCrtc( 203 bool RealOutputConfiguratorDelegate::ConfigureCrtc(
257 RRCrtc crtc, 204 RRCrtc crtc,
258 RRMode mode, 205 RRMode mode,
259 RROutput output, 206 RROutput output,
260 int x, 207 int x,
261 int y) { 208 int y) {
262 CHECK(screen_) << "Server not grabbed"; 209 CHECK(screen_) << "Server not grabbed";
263 VLOG(1) << "ConfigureCrtc: crtc=" << crtc 210 VLOG(1) << "ConfigureCrtc: crtc=" << crtc
264 << " mode=" << mode 211 << " mode=" << mode
265 << " output=" << output 212 << " output=" << output
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 284 }
338 XIFreeDeviceInfo(info); 285 XIFreeDeviceInfo(info);
339 } 286 }
340 287
341 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager( 288 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager(
342 bool projecting) { 289 bool projecting) {
343 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 290 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
344 SetIsProjecting(projecting); 291 SetIsProjecting(projecting);
345 } 292 }
346 293
294 bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
295 int* width,
296 int* height,
297 bool* interlaced) {
298 CHECK(screen_) << "Server not grabbed";
299 // TODO: Determine if we need to organize modes in a way which provides
300 // better than O(n) lookup time. In many call sites, for example, the
301 // "next" mode is typically what we are looking for so using this
302 // helper might be too expensive.
303 for (int i = 0; i < screen_->nmode; ++i) {
304 if (mode == screen_->modes[i].id) {
305 const XRRModeInfo& info = screen_->modes[i];
306 if (width)
307 *width = info.width;
308 if (height)
309 *height = info.height;
310 if (interlaced)
311 *interlaced = info.modeFlags & RR_Interlace;
312 return true;
313 }
314 }
315 return false;
316 }
317
318 OutputConfigurator::OutputSnapshot
319 RealOutputConfiguratorDelegate::InitOutputSnapshot(
320 RROutput id,
321 XRROutputInfo* info,
322 RRCrtc* last_used_crtc,
323 int index) {
324 OutputConfigurator::OutputSnapshot output;
325 output.output = id;
326 output.width_mm = info->mm_width;
327 output.height_mm = info->mm_height;
328 output.has_display_id = GetDisplayId(id, index, &output.display_id);
329 output.is_internal = IsInternalOutput(info);
330
331 // Use the index as a valid display ID even if the internal
332 // display doesn't have valid EDID because the index
333 // will never change.
334 if (!output.has_display_id && output.is_internal)
335 output.has_display_id = true;
336
337 if (info->crtc) {
338 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc);
339 output.current_mode = crtc_info->mode;
340 output.x = crtc_info->x;
341 output.y = crtc_info->y;
342 XRRFreeCrtcInfo(crtc_info);
343 }
344
345 // Assign a CRTC that isn't already in use.
346 for (int i = 0; i < info->ncrtc; ++i) {
347 if (info->crtcs[i] != *last_used_crtc) {
348 output.crtc = info->crtcs[i];
349 *last_used_crtc = output.crtc;
350 break;
351 }
352 }
353
354 output.native_mode = GetOutputNativeMode(info);
355 output.is_aspect_preserving_scaling = IsOutputAspectPreservingScaling(id);
356 output.touch_device_id = None;
357
358 for (int i = 0; i < info->nmode; ++i) {
359 const RRMode mode = info->modes[i];
360 OutputConfigurator::ModeInfo mode_info;
361 if (GetModeDetails(mode, &mode_info.width, &mode_info.height,
362 &mode_info.interlaced)) {
363 output.mode_infos.insert(std::make_pair(mode, mode_info));
364 } else {
365 LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
366 }
367 }
368
369 return output;
370 }
371
347 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( 372 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
348 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { 373 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
349 CHECK(screen_) << "Server not grabbed"; 374 CHECK(screen_) << "Server not grabbed";
350 // Setting the screen size will fail if any CRTC doesn't fit afterwards. 375 // Setting the screen size will fail if any CRTC doesn't fit afterwards.
351 // At the same time, turning CRTCs off and back on uses up a lot of time. 376 // At the same time, turning CRTCs off and back on uses up a lot of time.
352 // This function tries to be smart to avoid too many off/on cycles: 377 // This function tries to be smart to avoid too many off/on cycles:
353 // - We disable all the CRTCs we won't need after the FB resize. 378 // - We disable all the CRTCs we won't need after the FB resize.
354 // - We set the new modes on CRTCs, if they fit in both the old and new 379 // - We set the new modes on CRTCs, if they fit in both the old and new
355 // FBs, and park them at (0,0) 380 // FBs, and park them at (0,0)
356 // - We disable the CRTCs we will need but don't fit in the old FB. Those 381 // - We disable the CRTCs we will need but don't fit in the old FB. Those
357 // will be reenabled after the resize. 382 // will be reenabled after the resize.
358 // We don't worry about the cached state of the outputs here since we are 383 // We don't worry about the cached state of the outputs here since we are
359 // not interested in the state we are setting - we just try to get the CRTCs 384 // not interested in the state we are setting - we just try to get the CRTCs
360 // out of the way so we can rebuild the frame buffer. 385 // out of the way so we can rebuild the frame buffer.
361 for (int i = 0; i < screen_->ncrtc; ++i) { 386 for (int i = 0; i < screen_->ncrtc; ++i) {
362 // Default config is to disable the crtcs. 387 // Default config is to disable the crtcs.
363 RRCrtc crtc = screen_->crtcs[i]; 388 RRCrtc crtc = screen_->crtcs[i];
364 RRMode mode = None; 389 RRMode mode = None;
365 RROutput output = None; 390 RROutput output = None;
391 const OutputConfigurator::ModeInfo* mode_info = NULL;
366 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it = 392 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
367 outputs.begin(); it != outputs.end(); ++it) { 393 outputs.begin(); it != outputs.end(); ++it) {
368 if (crtc == it->crtc) { 394 if (crtc == it->crtc) {
369 mode = it->current_mode; 395 mode = it->current_mode;
370 output = it->output; 396 output = it->output;
397 if (mode != None)
398 mode_info = OutputConfigurator::GetModeInfo(*it, mode);
371 break; 399 break;
372 } 400 }
373 } 401 }
374 402
375 if (mode != None) { 403 if (mode_info) {
376 // In case our CRTC doesn't fit in our current framebuffer, disable it. 404 // In case our CRTC doesn't fit in our current framebuffer, disable it.
377 // It'll get reenabled after we resize the framebuffer. 405 // It'll get reenabled after we resize the framebuffer.
378 int mode_width = 0, mode_height = 0;
379 CHECK(GetModeDetails(mode, &mode_width, &mode_height, NULL));
380 int current_width = DisplayWidth(display_, DefaultScreen(display_)); 406 int current_width = DisplayWidth(display_, DefaultScreen(display_));
381 int current_height = DisplayHeight(display_, DefaultScreen(display_)); 407 int current_height = DisplayHeight(display_, DefaultScreen(display_));
382 if (mode_width > current_width || mode_height > current_height) { 408 if (mode_info->width > current_width ||
409 mode_info->height > current_height) {
383 mode = None; 410 mode = None;
384 output = None; 411 output = None;
412 mode_info = NULL;
385 } 413 }
386 } 414 }
387 415
388 ConfigureCrtc(crtc, mode, output, 0, 0); 416 ConfigureCrtc(crtc, mode, output, 0, 0);
389 } 417 }
390 } 418 }
391 419
392 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling( 420 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling(
393 RROutput id) { 421 RROutput id) {
394 bool ret = false; 422 bool ret = false;
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 is_direct_touch = touch_info->mode == XIDirectTouch; 577 is_direct_touch = touch_info->mode == XIDirectTouch;
550 } 578 }
551 #endif 579 #endif
552 } 580 }
553 581
554 // Touchscreens should have absolute X and Y axes, 582 // Touchscreens should have absolute X and Y axes,
555 // and be direct touch devices. 583 // and be direct touch devices.
556 if (width > 0.0 && height > 0.0 && is_direct_touch) { 584 if (width > 0.0 && height > 0.0 && is_direct_touch) {
557 size_t k = 0; 585 size_t k = 0;
558 for (; k < outputs->size(); k++) { 586 for (; k < outputs->size(); k++) {
559 if ((*outputs)[k].native_mode == None || 587 OutputConfigurator::OutputSnapshot* output = &(*outputs)[k];
560 (*outputs)[k].touch_device_id != None) 588 if (output->native_mode == None || output->touch_device_id != None)
561 continue; 589 continue;
562 int native_mode_width = 0, native_mode_height = 0; 590
563 if (!GetModeDetails((*outputs)[k].native_mode, &native_mode_width, 591 const OutputConfigurator::ModeInfo* mode_info =
564 &native_mode_height, NULL)) 592 OutputConfigurator::GetModeInfo(*output, output->native_mode);
593 if (!mode_info)
565 continue; 594 continue;
566 595
567 // Allow 1 pixel difference between screen and touchscreen 596 // Allow 1 pixel difference between screen and touchscreen
568 // resolutions. Because in some cases for monitor resolution 597 // resolutions. Because in some cases for monitor resolution
569 // 1024x768 touchscreen's resolution would be 1024x768, but for 598 // 1024x768 touchscreen's resolution would be 1024x768, but for
570 // some 1023x767. It really depends on touchscreen's firmware 599 // some 1023x767. It really depends on touchscreen's firmware
571 // configuration. 600 // configuration.
572 if (std::abs(native_mode_width - width) <= 1.0 && 601 if (std::abs(mode_info->width - width) <= 1.0 &&
573 std::abs(native_mode_height - height) <= 1.0) { 602 std::abs(mode_info->height - height) <= 1.0) {
574 (*outputs)[k].touch_device_id = info[i].deviceid; 603 output->touch_device_id = info[i].deviceid;
575 604
576 VLOG(2) << "Found touchscreen for output #" << k 605 VLOG(2) << "Found touchscreen for output #" << k
577 << " id " << (*outputs)[k].touch_device_id 606 << " id " << output->touch_device_id
578 << " width " << width 607 << " width " << width
579 << " height " << height; 608 << " height " << height;
580 break; 609 break;
581 } 610 }
582 } 611 }
583 612
584 if (k == outputs->size()) { 613 if (k == outputs->size()) {
585 no_match_touchscreen.insert(info[i].deviceid); 614 no_match_touchscreen.insert(info[i].deviceid);
586 VLOG(2) << "No matching output for touchscreen" 615 VLOG(2) << "No matching output for touchscreen"
587 << " id " << info[i].deviceid 616 << " id " << info[i].deviceid
(...skipping 20 matching lines...) Expand all
608 << (*outputs)[i].touch_device_id << " to output #" << i; 637 << (*outputs)[i].touch_device_id << " to output #" << i;
609 break; 638 break;
610 } 639 }
611 } 640 }
612 } 641 }
613 642
614 XIFreeDeviceInfo(info); 643 XIFreeDeviceInfo(info);
615 } 644 }
616 645
617 } // namespace chromeos 646 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/display/real_output_configurator_delegate.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698