summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chromeos/display/output_configurator.cc251
-rw-r--r--chromeos/display/output_configurator.h39
-rw-r--r--content/browser/gpu/software_rendering_list.json6
3 files changed, 144 insertions, 152 deletions
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index dea239c..95410be 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -79,63 +79,6 @@ static XRRModeInfo* ModeInfoForID(XRRScreenResources* screen, RRMode modeID) {
return result;
}
-// Identifies the modes which will be used by the respective outputs when in a
-// mirror mode. This means that the two modes will have the same resolution.
-// The RROutput IDs |one| and |two| are used to look up the modes and
-// |out_one_mode| and |out_two_mode| are the out-parameters for the respective
-// modes.
-// Returns false if it fails to find a compatible set of modes.
-static bool FindMirrorModeForOutputs(Display* display,
- XRRScreenResources* screen,
- RROutput one,
- RROutput two,
- RRMode* out_one_mode,
- RRMode* out_two_mode) {
- XRROutputInfo* primary = XRRGetOutputInfo(display, screen, one);
- XRROutputInfo* secondary = XRRGetOutputInfo(display, screen, two);
-
- int one_index = 0;
- int two_index = 0;
- bool found = false;
- while (!found &&
- (one_index < primary->nmode) &&
- (two_index < secondary->nmode)) {
- RRMode one_id = primary->modes[one_index];
- RRMode two_id = secondary->modes[two_index];
- XRRModeInfo* one_mode = ModeInfoForID(screen, one_id);
- XRRModeInfo* two_mode = ModeInfoForID(screen, two_id);
- if (one_mode == NULL || two_mode == NULL)
- break;
-
- int one_width = one_mode->width;
- int one_height = one_mode->height;
- int two_width = two_mode->width;
- int two_height = two_mode->height;
- if ((one_width == two_width) && (one_height == two_height)) {
- *out_one_mode = one_id;
- *out_two_mode = two_id;
- found = true;
- } else {
- // The sort order of the modes is NOT by mode area but is sorted by width,
- // then by height within each like width.
- if (one_width > two_width) {
- one_index += 1;
- } else if (one_width < two_width) {
- two_index += 1;
- } else {
- if (one_height > two_height) {
- one_index += 1;
- } else {
- two_index += 1;
- }
- }
- }
- }
- XRRFreeOutputInfo(primary);
- XRRFreeOutputInfo(secondary);
- return found;
-}
-
// A helper to call XRRSetCrtcConfig with the given options but some of our
// default output count and rotation arguments.
static void ConfigureCrtc(Display* display,
@@ -857,26 +800,76 @@ int OutputConfigurator::GetDualOutputs(Display* display,
}
if (2 == found_count) {
- // Find the mirror modes (if there are any).
- bool mirror_mode_found = FindMirrorModeForOutputs(display,
- screen,
- one->output,
- two->output,
- &one->mirror_mode,
- &two->mirror_mode);
- if (!mirror_mode_found) {
- bool mirror_mode_added = AddMirrorModeToInternalOutput(display,
- screen,
- one->output,
- two->output,
- &one->mirror_mode,
- &two->mirror_mode);
- if (!mirror_mode_added) {
- // We can't mirror so set mirror_mode to 0.
- one->mirror_mode = 0;
- two->mirror_mode = 0;
+ bool one_is_internal = IsInternalOutput(one_info);
+ bool two_is_internal = IsInternalOutput(two_info);
+ int internal_outputs = one_is_internal ? 1 : 0 + two_is_internal ? 1 : 0;
+
+ DCHECK(internal_outputs < 2);
+ LOG_IF(WARNING, internal_outputs == 2) << "Two internal outputs detected.";
+
+ bool can_mirror = false;
+
+ for (int attempt = 0; attempt < 2 && !can_mirror; attempt++) {
+ // Try preserving external output's aspect ratio on the first attempt
+ // If that fails, fall back to the highest matching resolution
+ bool preserve_aspect = attempt == 0;
+
+ if (internal_outputs == 1) {
+ if (one_is_internal) {
+ can_mirror = FindOrCreateMirrorMode(display,
+ screen,
+ one_info,
+ two_info,
+ one->output,
+ is_panel_fitting_enabled_,
+ preserve_aspect,
+ &one->mirror_mode,
+ &two->mirror_mode);
+ } else { // if (two_is_internal)
+ can_mirror = FindOrCreateMirrorMode(display,
+ screen,
+ two_info,
+ one_info,
+ two->output,
+ is_panel_fitting_enabled_,
+ preserve_aspect,
+ &two->mirror_mode,
+ &one->mirror_mode);
+ }
+ } else { // if (internal_outputs == 0)
+ // No panel fitting for external outputs, so fall back to exact match
+ can_mirror = FindOrCreateMirrorMode(display,
+ screen,
+ one_info,
+ two_info,
+ one->output,
+ false,
+ preserve_aspect,
+ &one->mirror_mode,
+ &two->mirror_mode);
+ if (!can_mirror && preserve_aspect) {
+ // FindOrCreateMirrorMode will try to preserve aspect ratio of
+ // what it thinks is external display, so if it didn't succeed
+ // with one, maybe it will succeed with the other.
+ // This way we will have correct aspect ratio on at least one of them.
+ can_mirror = FindOrCreateMirrorMode(display,
+ screen,
+ two_info,
+ one_info,
+ two->output,
+ false,
+ preserve_aspect,
+ &two->mirror_mode,
+ &one->mirror_mode);
+ }
}
}
+
+ if (!can_mirror) {
+ // We can't mirror so set mirror_mode to None.
+ one->mirror_mode = None;
+ two->mirror_mode = None;
+ }
}
XRRFreeOutputInfo(one_info);
@@ -884,73 +877,67 @@ int OutputConfigurator::GetDualOutputs(Display* display,
return found_count;
}
-bool OutputConfigurator::AddMirrorModeToInternalOutput(
+bool OutputConfigurator::FindOrCreateMirrorMode(
Display* display,
XRRScreenResources* screen,
- RROutput output_one,
- RROutput output_two,
- RRMode* output_one_mode,
- RRMode* output_two_mode) {
- // Add new mode only if panel fitting hardware will be able to display it.
- if (!is_panel_fitting_enabled_)
+ XRROutputInfo* internal_info,
+ XRROutputInfo* external_info,
+ RROutput internal_output_id,
+ bool try_creating,
+ bool preserve_aspect,
+ RRMode* internal_mirror_mode,
+ RRMode* external_mirror_mode) {
+ RRMode internal_mode_id = GetOutputNativeMode(internal_info);
+ RRMode external_mode_id = GetOutputNativeMode(external_info);
+
+ if (internal_mode_id == None || external_mode_id == None)
return false;
- XRROutputInfo* output_one_info =
- XRRGetOutputInfo(display, screen, output_one);
- XRROutputInfo* output_two_info =
- XRRGetOutputInfo(display, screen, output_two);
- bool success = false;
-
- // Both outputs should be connected in mirror mode
- if (output_one_info->connection == RR_Connected &&
- output_two_info->connection == RR_Connected) {
- bool one_is_internal = IsInternalOutput(output_one_info);
- bool two_is_internal = IsInternalOutput(output_two_info);
-
- XRROutputInfo* internal_info = NULL;
- XRROutputInfo* external_info = NULL;
-
- if (one_is_internal) {
- internal_info = output_one_info;
- external_info = output_two_info;
-
- VLOG_IF(1, two_is_internal) << "Two internal outputs detected.";
- DCHECK(!two_is_internal);
- } else if (two_is_internal) {
- internal_info = output_two_info;
- external_info = output_one_info;
+ XRRModeInfo* internal_native_mode = ModeInfoForID(screen, internal_mode_id);
+ XRRModeInfo* external_native_mode = ModeInfoForID(screen, external_mode_id);
+
+ // Check if some external output resolution can be mirrored on internal.
+ // Prefer the modes in the order that X sorts them,
+ // assuming this is the order in which they look better on the monitor.
+ // If X's order is not satisfactory, we can either fix X's sorting,
+ // or implement our sorting here.
+ for (int i = 0; i < external_info->nmode; i++) {
+ external_mode_id = external_info->modes[i];
+ XRRModeInfo* external_mode = ModeInfoForID(screen, external_mode_id);
+ bool is_native_aspect_ratio =
+ external_native_mode->width * external_mode->height ==
+ external_native_mode->height * external_mode->width;
+ if (preserve_aspect && !is_native_aspect_ratio)
+ continue; // Allow only aspect ratio preserving modes for mirroring
+
+ // Try finding exact match
+ for (int j = 0; j < internal_info->nmode; j++) {
+ internal_mode_id = internal_info->modes[j];
+ XRRModeInfo* internal_mode = ModeInfoForID(screen, internal_mode_id);
+ if (internal_mode->width == external_mode->width &&
+ internal_mode->height == external_mode->height) {
+ *internal_mirror_mode = internal_mode_id;
+ *external_mirror_mode = external_mode_id;
+ return true; // Mirror mode found
+ }
}
- bool internal_output_found = internal_info != NULL;
-
- if (internal_output_found) {
- RRMode internal_native_mode_id = GetOutputNativeMode(internal_info);
- RRMode external_native_mode_id = GetOutputNativeMode(external_info);
-
- if (internal_native_mode_id != None && external_native_mode_id != None) {
- XRRModeInfo* internal_native_mode =
- ModeInfoForID(screen, internal_native_mode_id);
- XRRModeInfo* external_native_mode =
- ModeInfoForID(screen, external_native_mode_id);
-
- // Panel fitting will not work if the internal output maximal resolution
- // is lower than that of the external output
- if (internal_native_mode->width >= external_native_mode->width &&
- internal_native_mode->height >= external_native_mode->height) {
- XRRAddOutputMode(display, one_is_internal ? output_one : output_two,
- external_native_mode_id);
-
- *output_one_mode = *output_two_mode = external_native_mode_id;
- success = true;
- }
+ // Try to create a matching internal output mode by panel fitting
+ if (try_creating) {
+ // We can downscale by 1.125, and upscale indefinitely
+ // Downscaling looks ugly, so, can fit == can upscale
+ bool can_fit =
+ internal_native_mode->width >= external_mode->width &&
+ internal_native_mode->height >= external_mode->height;
+ if (can_fit) {
+ XRRAddOutputMode(display, internal_output_id, external_mode_id);
+ *internal_mirror_mode = *external_mirror_mode = external_mode_id;
+ return true; // Mirror mode created
}
}
}
- XRRFreeOutputInfo(output_one_info);
- XRRFreeOutputInfo(output_two_info);
-
- return success;
+ return false;
}
// static
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index df5f638..b52a4b6 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -110,23 +110,28 @@ class CHROMEOS_EXPORT OutputConfigurator : public MessageLoop::Dispatcher {
OutputSnapshot* one,
OutputSnapshot* two);
- // Should be called if the internal (built-in) output didn't advertise a mode
- // which would be capable to support mirror mode.
- // Relies on hardware panel fitting support,
- // returns immediately if it is not available.
- // Tries to add the native mode of the external output to the internal output,
- // assuming panel fitter hardware will take care of scaling and letterboxing.
- // The RROutput IDs |output_one| and |output_two| are used
- // to look up the modes and configure the internal output,
- // |output_one_mode| and |output_two_mode| are the out-parameters
- // for the modes on the two outputs which will have same resolution.
- // Returns false if it fails to configure the internal output appropriately.
- bool AddMirrorModeToInternalOutput(Display* display,
- XRRScreenResources* screen,
- RROutput output_one,
- RROutput output_two,
- RRMode* output_one_mode,
- RRMode* output_two_mode);
+ // Looks for a mode on internal and external outputs having same resolution.
+ // |display| and |screen| parameters are needed for some XRandR calls.
+ // |internal_info| and |external_info| are used to search for the modes.
+ // |internal_output_id| is used to create a new mode, if applicable.
+ // |try_creating|=true will enable creating panel-fitting mode
+ // on the |internal_info| output instead of
+ // only searching for a matching mode. Note: it may lead to a crash,
+ // if |internal_info| is not capable of panel fitting.
+ // |preserve_aspect|=true will limit the search / creation
+ // only to the modes having the native aspect ratio of |external_info|.
+ // |internal_mirror_mode| and |external_mirror_mode| are the out-parameters
+ // for the modes on the two outputs which will have the same resolution.
+ // Returns false if no mode appropriate for mirroring has been found/created.
+ bool FindOrCreateMirrorMode(Display* display,
+ XRRScreenResources* screen,
+ XRROutputInfo* internal_info,
+ XRROutputInfo* external_info,
+ RROutput internal_output_id,
+ bool try_creating,
+ bool preserve_aspect,
+ RRMode* internal_mirror_mode,
+ RRMode* external_mirror_mode);
// Tells if the output specified by |output_info| is for internal display.
static bool IsInternalOutput(const XRROutputInfo* output_info);
diff --git a/content/browser/gpu/software_rendering_list.json b/content/browser/gpu/software_rendering_list.json
index df396a9..e1736af 100644
--- a/content/browser/gpu/software_rendering_list.json
+++ b/content/browser/gpu/software_rendering_list.json
@@ -74,7 +74,7 @@
{
"name": "software rendering list",
// Please update the version number whenever you change this file.
- "version": "4.7",
+ "version": "4.8",
"entries": [
{
"id": 1,
@@ -847,14 +847,14 @@
},
{
"id": 57,
- "description": "Enable panel fitting capability on ChromeOS only on Ivy Bridge Graphics Controller.",
+ "description": "Enable panel fitting capability on ChromeOS only on IVB and SNB Graphics Controllers.",
"exceptions": [
{
"os": {
"type": "chromeos"
},
"vendor_id": "0x8086",
- "device_id": ["0x0166"]
+ "device_id": ["0x0106", "0x0116", "0x0166"]
}
],
"blacklist": [