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

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 InitOutputSnapshot() 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 <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 (outputs.empty() ? one_info : two_info) = output_info;
135 129
136 // Now, look up the current CRTC and any related info. 130 OutputConfigurator::OutputSnapshot output = InitOutputSnapshot(
137 if (output_info->crtc) { 131 output_id, output_info, &last_used_crtc, i, state_controller);
138 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo( 132 VLOG(2) << "Found display " << outputs.size() << ":"
139 display_, screen_, output_info->crtc); 133 << " output=" << output.output
140 to_populate.current_mode = crtc_info->mode; 134 << " crtc=" << output.crtc
141 to_populate.x = crtc_info->x; 135 << " current_mode=" << output.current_mode;
142 to_populate.y = crtc_info->y; 136 outputs.push_back(output);
143 XRRFreeCrtcInfo(crtc_info);
144 }
145
146 // Assign a CRTC that isn't already in use.
147 for (int j = 0; j < output_info->ncrtc; ++j) {
148 if (output_info->crtcs[j] != last_used_crtc) {
149 to_populate.crtc = output_info->crtcs[j];
150 last_used_crtc = to_populate.crtc;
151 break;
152 }
153 }
154 to_populate.native_mode = GetOutputNativeMode(output_info);
155 if (to_populate.has_display_id) {
156 int width = 0, height = 0;
157 if (state_controller &&
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
168 to_populate.is_aspect_preserving_scaling =
169 IsOutputAspectPreservingScaling(this_id);
170 to_populate.touch_device_id = None;
171
172 VLOG(2) << "Found display " << outputs.size() << ":"
173 << " output=" << to_populate.output
174 << " crtc=" << to_populate.crtc
175 << " current_mode=" << to_populate.current_mode;
176 outputs.push_back(to_populate);
177 } else {
178 XRRFreeOutputInfo(output_info);
179 }
180 } 137 }
181 138
182 if (outputs.size() == 2) { 139 if (outputs.size() == 2) {
183 bool one_is_internal = IsInternalOutput(one_info); 140 bool one_is_internal = IsInternalOutput(one_info);
184 bool two_is_internal = IsInternalOutput(two_info); 141 bool two_is_internal = IsInternalOutput(two_info);
185 int internal_outputs = (one_is_internal ? 1 : 0) + 142 int internal_outputs = (one_is_internal ? 1 : 0) +
186 (two_is_internal ? 1 : 0); 143 (two_is_internal ? 1 : 0);
187 DCHECK_LT(internal_outputs, 2); 144 DCHECK_LT(internal_outputs, 2);
188 LOG_IF(WARNING, internal_outputs == 2) 145 LOG_IF(WARNING, internal_outputs == 2)
189 << "Two internal outputs detected."; 146 << "Two internal outputs detected.";
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 } 178 }
222 } 179 }
223 } 180 }
224 181
225 GetTouchscreens(&outputs); 182 GetTouchscreens(&outputs);
226 XRRFreeOutputInfo(one_info); 183 XRRFreeOutputInfo(one_info);
227 XRRFreeOutputInfo(two_info); 184 XRRFreeOutputInfo(two_info);
228 return outputs; 185 return outputs;
229 } 186 }
230 187
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( 188 bool RealOutputConfiguratorDelegate::ConfigureCrtc(
256 RRCrtc crtc, 189 RRCrtc crtc,
257 RRMode mode, 190 RRMode mode,
258 RROutput output, 191 RROutput output,
259 int x, 192 int x,
260 int y) { 193 int y) {
261 CHECK(screen_) << "Server not grabbed"; 194 CHECK(screen_) << "Server not grabbed";
262 VLOG(1) << "ConfigureCrtc: crtc=" << crtc 195 VLOG(1) << "ConfigureCrtc: crtc=" << crtc
263 << " mode=" << mode 196 << " mode=" << mode
264 << " output=" << output 197 << " output=" << output
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 } 269 }
337 XIFreeDeviceInfo(info); 270 XIFreeDeviceInfo(info);
338 } 271 }
339 272
340 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager( 273 void RealOutputConfiguratorDelegate::SendProjectingStateToPowerManager(
341 bool projecting) { 274 bool projecting) {
342 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 275 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
343 SetIsProjecting(projecting); 276 SetIsProjecting(projecting);
344 } 277 }
345 278
279 bool RealOutputConfiguratorDelegate::GetModeDetails(RRMode mode,
280 int* width,
281 int* height,
282 bool* interlaced) {
283 CHECK(screen_) << "Server not grabbed";
284 // TODO: Determine if we need to organize modes in a way which provides
285 // better than O(n) lookup time. In many call sites, for example, the
286 // "next" mode is typically what we are looking for so using this
287 // helper might be too expensive.
288 for (int i = 0; i < screen_->nmode; ++i) {
289 if (mode == screen_->modes[i].id) {
290 const XRRModeInfo& info = screen_->modes[i];
291 if (width)
292 *width = info.width;
293 if (height)
294 *height = info.height;
295 if (interlaced)
296 *interlaced = info.modeFlags & RR_Interlace;
297 return true;
298 }
299 }
300 return false;
301 }
302
303 OutputConfigurator::OutputSnapshot
304 RealOutputConfiguratorDelegate::InitOutputSnapshot(
305 RROutput id,
306 XRROutputInfo* info,
307 RRCrtc* last_used_crtc,
308 int index,
309 const OutputConfigurator::StateController* state_controller) {
310 OutputConfigurator::OutputSnapshot output;
311 output.output = id;
312 output.width_mm = info->mm_width;
313 output.height_mm = info->mm_height;
314 output.has_display_id = GetDisplayId(id, index, &output.display_id);
315 output.is_internal = IsInternalOutput(info);
316
317 // Use the index as a valid display ID even if the internal
318 // display doesn't have valid EDID because the index
319 // will never change.
320 if (!output.has_display_id && output.is_internal)
321 output.has_display_id = true;
322
323 if (info->crtc) {
324 XRRCrtcInfo* crtc_info = XRRGetCrtcInfo(display_, screen_, info->crtc);
325 output.current_mode = crtc_info->mode;
326 output.x = crtc_info->x;
327 output.y = crtc_info->y;
328 XRRFreeCrtcInfo(crtc_info);
329 }
330
331 // Assign a CRTC that isn't already in use.
332 for (int i = 0; i < info->ncrtc; ++i) {
333 if (info->crtcs[i] != *last_used_crtc) {
334 output.crtc = info->crtcs[i];
335 *last_used_crtc = output.crtc;
336 break;
337 }
338 }
339
340 output.native_mode = GetOutputNativeMode(info);
341
342 if (output.has_display_id) {
343 int width = 0, height = 0;
344 if (state_controller &&
345 state_controller->GetResolutionForDisplayId(
346 output.display_id, &width, &height)) {
347 output.selected_mode =
348 FindOutputModeMatchingSize(screen_, info, width, height);
349 }
350 }
351 // Fall back to native mode.
352 if (output.selected_mode == None)
353 output.selected_mode = output.native_mode;
oshima 2013/08/15 21:35:59 finding selected_mode could have been done after t
Daniel Erat 2013/08/15 21:57:22 Done.
354
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
346 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs( 372 void RealOutputConfiguratorDelegate::DestroyUnusedCrtcs(
347 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) { 373 const std::vector<OutputConfigurator::OutputSnapshot>& outputs) {
348 CHECK(screen_) << "Server not grabbed"; 374 CHECK(screen_) << "Server not grabbed";
349 // 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.
350 // 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.
351 // 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:
352 // - 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.
353 // - 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
354 // FBs, and park them at (0,0) 380 // FBs, and park them at (0,0)
355 // - 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
356 // will be reenabled after the resize. 382 // will be reenabled after the resize.
357 // 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
358 // 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
359 // out of the way so we can rebuild the frame buffer. 385 // out of the way so we can rebuild the frame buffer.
360 for (int i = 0; i < screen_->ncrtc; ++i) { 386 for (int i = 0; i < screen_->ncrtc; ++i) {
361 // Default config is to disable the crtcs. 387 // Default config is to disable the crtcs.
362 RRCrtc crtc = screen_->crtcs[i]; 388 RRCrtc crtc = screen_->crtcs[i];
363 RRMode mode = None; 389 RRMode mode = None;
364 RROutput output = None; 390 RROutput output = None;
391 const OutputConfigurator::ModeInfo* mode_info = NULL;
365 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it = 392 for (std::vector<OutputConfigurator::OutputSnapshot>::const_iterator it =
366 outputs.begin(); it != outputs.end(); ++it) { 393 outputs.begin(); it != outputs.end(); ++it) {
367 if (crtc == it->crtc) { 394 if (crtc == it->crtc) {
368 mode = it->current_mode; 395 mode = it->current_mode;
369 output = it->output; 396 output = it->output;
397 mode_info = OutputConfigurator::GetModeInfo(*it, mode);
370 break; 398 break;
371 } 399 }
372 } 400 }
373 401
374 if (mode != None) { 402 if (mode_info) {
375 // In case our CRTC doesn't fit in our current framebuffer, disable it. 403 // In case our CRTC doesn't fit in our current framebuffer, disable it.
376 // It'll get reenabled after we resize the framebuffer. 404 // 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_)); 405 int current_width = DisplayWidth(display_, DefaultScreen(display_));
380 int current_height = DisplayHeight(display_, DefaultScreen(display_)); 406 int current_height = DisplayHeight(display_, DefaultScreen(display_));
381 if (mode_width > current_width || mode_height > current_height) { 407 if (mode_info->width > current_width ||
408 mode_info->height > current_height) {
382 mode = None; 409 mode = None;
383 output = None; 410 output = None;
411 mode_info = NULL;
384 } 412 }
385 } 413 }
386 414
387 ConfigureCrtc(crtc, mode, output, 0, 0); 415 ConfigureCrtc(crtc, mode, output, 0, 0);
388 } 416 }
389 } 417 }
390 418
391 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling( 419 bool RealOutputConfiguratorDelegate::IsOutputAspectPreservingScaling(
392 RROutput id) { 420 RROutput id) {
393 bool ret = false; 421 bool ret = false;
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 is_direct_touch = touch_info->mode == XIDirectTouch; 575 is_direct_touch = touch_info->mode == XIDirectTouch;
548 } 576 }
549 #endif 577 #endif
550 } 578 }
551 579
552 // Touchscreens should have absolute X and Y axes, 580 // Touchscreens should have absolute X and Y axes,
553 // and be direct touch devices. 581 // and be direct touch devices.
554 if (width > 0.0 && height > 0.0 && is_direct_touch) { 582 if (width > 0.0 && height > 0.0 && is_direct_touch) {
555 size_t k = 0; 583 size_t k = 0;
556 for (; k < outputs->size(); k++) { 584 for (; k < outputs->size(); k++) {
557 if ((*outputs)[k].native_mode == None || 585 OutputConfigurator::OutputSnapshot* output = &(*outputs)[k];
558 (*outputs)[k].touch_device_id != None) 586 if (output->native_mode == None || output->touch_device_id != None)
559 continue; 587 continue;
560 int native_mode_width = 0, native_mode_height = 0; 588
561 if (!GetModeDetails((*outputs)[k].native_mode, &native_mode_width, 589 const OutputConfigurator::ModeInfo* mode_info =
562 &native_mode_height, NULL)) 590 OutputConfigurator::GetModeInfo(*output, output->native_mode);
591 if (!mode_info)
563 continue; 592 continue;
564 593
565 // Allow 1 pixel difference between screen and touchscreen 594 // Allow 1 pixel difference between screen and touchscreen
566 // resolutions. Because in some cases for monitor resolution 595 // resolutions. Because in some cases for monitor resolution
567 // 1024x768 touchscreen's resolution would be 1024x768, but for 596 // 1024x768 touchscreen's resolution would be 1024x768, but for
568 // some 1023x767. It really depends on touchscreen's firmware 597 // some 1023x767. It really depends on touchscreen's firmware
569 // configuration. 598 // configuration.
570 if (std::abs(native_mode_width - width) <= 1.0 && 599 if (std::abs(mode_info->width - width) <= 1.0 &&
571 std::abs(native_mode_height - height) <= 1.0) { 600 std::abs(mode_info->height - height) <= 1.0) {
572 (*outputs)[k].touch_device_id = info[i].deviceid; 601 output->touch_device_id = info[i].deviceid;
573 602
574 VLOG(2) << "Found touchscreen for output #" << k 603 VLOG(2) << "Found touchscreen for output #" << k
575 << " id " << (*outputs)[k].touch_device_id 604 << " id " << output->touch_device_id
576 << " width " << width 605 << " width " << width
577 << " height " << height; 606 << " height " << height;
578 break; 607 break;
579 } 608 }
580 } 609 }
581 610
582 VLOG_IF(2, k == outputs->size()) 611 VLOG_IF(2, k == outputs->size())
583 << "No matching output - ignoring touchscreen" 612 << "No matching output - ignoring touchscreen"
584 << " id " << info[i].deviceid 613 << " id " << info[i].deviceid
585 << " width " << width 614 << " width " << width
586 << " height " << height; 615 << " height " << height;
587 } 616 }
588 } 617 }
589 618
590 XIFreeDeviceInfo(info); 619 XIFreeDeviceInfo(info);
591 } 620 }
592 621
593 } // namespace chromeos 622 } // 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