summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/display/output_configurator.cc51
-rw-r--r--chromeos/display/output_configurator.h9
-rw-r--r--chromeos/display/output_configurator_unittest.cc40
3 files changed, 90 insertions, 10 deletions
diff --git a/chromeos/display/output_configurator.cc b/chromeos/display/output_configurator.cc
index 1a3cc31..67da273 100644
--- a/chromeos/display/output_configurator.cc
+++ b/chromeos/display/output_configurator.cc
@@ -932,16 +932,8 @@ bool OutputConfigurator::EnterState(
for (size_t i = 0; i < updated_outputs.size(); ++i) {
OutputSnapshot* output = &updated_outputs[i];
- if (output->touch_device_id) {
- const ModeInfo* mode_info =
- GetModeInfo(*output, output->selected_mode);
- DCHECK(mode_info);
- CoordinateTransformation* ctm = &(output->transform);
- ctm->x_scale = static_cast<float>(mode_info->width) / width;
- ctm->x_offset = static_cast<float>(output->x) / width;
- ctm->y_scale = static_cast<float>(mode_info->height) / height;
- ctm->y_offset = static_cast<float>(output->y) / height;
- }
+ if (output->touch_device_id)
+ output->transform = GetExtendedModeCTM(*output, width, height);
}
break;
}
@@ -1040,6 +1032,45 @@ OutputConfigurator::GetMirrorModeCTM(
return ctm; // Same aspect ratio - return identity
}
+OutputConfigurator::CoordinateTransformation
+OutputConfigurator::GetExtendedModeCTM(
+ const OutputConfigurator::OutputSnapshot& output,
+ int framebuffer_width,
+ int framebuffer_height) {
+ CoordinateTransformation ctm; // Default to identity
+ const ModeInfo* mode_info = GetModeInfo(output, output.selected_mode);
+ DCHECK(mode_info);
+ if (!mode_info)
+ return ctm;
+ // An example of how to calculate the CTM.
+ // Suppose we have 2 monitors, the first one has size 1366 x 768.
+ // The second one has size 2560 x 1600
+ // The total size of framebuffer is 2560 x 2428
+ // where 2428 = 768 + 60 (hidden gap) + 1600
+ // and the sceond monitor is translated to Point (0, 828) in the
+ // framebuffer.
+ // X will first map input event location to [0, 2560) x [0, 2428),
+ // then apply CTM on it.
+ // So to compute CTM, for monitor1, we have
+ // x_scale = (1366 - 1) / (2560 - 1)
+ // x_offset = 0 / (2560 - 1)
+ // y_scale = (768 - 1) / (2428 - 1)
+ // y_offset = 0 / (2428 -1)
+ // For Monitor 2, we have
+ // x_scale = (2560 - 1) / (2560 - 1)
+ // x_offset = 0 / (2560 - 1)
+ // y_scale = (1600 - 1) / (2428 - 1)
+ // y_offset = 828 / (2428 -1)
+ // See the unittest OutputConfiguratorTest.CTMForMultiScreens.
+ ctm.x_scale =
+ static_cast<float>(mode_info->width - 1) / (framebuffer_width - 1);
+ ctm.x_offset = static_cast<float>(output.x) / (framebuffer_width - 1);
+ ctm.y_scale =
+ static_cast<float>(mode_info->height - 1) / (framebuffer_height - 1);
+ ctm.y_offset = static_cast<float>(output.y) / (framebuffer_height - 1);
+ return ctm;
+}
+
float OutputConfigurator::GetMirroredDisplayAreaRatio(
const OutputConfigurator::OutputSnapshot& output) {
float area_ratio = 1.0f;
diff --git a/chromeos/display/output_configurator.h b/chromeos/display/output_configurator.h
index ef5085e..c927519 100644
--- a/chromeos/display/output_configurator.h
+++ b/chromeos/display/output_configurator.h
@@ -487,6 +487,15 @@ class CHROMEOS_EXPORT OutputConfigurator
CoordinateTransformation GetMirrorModeCTM(
const OutputConfigurator::OutputSnapshot& output);
+ // Computes the relevant transformation for extended mode.
+ // |output| is the output on which extended mode is being applied.
+ // |width| and |height| are the width and height of the combined framebuffer.
+ // Returns the transformation or identity if computations fail.
+ CoordinateTransformation GetExtendedModeCTM(
+ const OutputConfigurator::OutputSnapshot& output,
+ int framebuffer_width,
+ int frame_buffer_height);
+
// Returns the ratio between mirrored mode area and native mode area:
// (mirror_mode_width * mirrow_mode_height) / (native_width * native_height)
float GetMirroredDisplayAreaRatio(
diff --git a/chromeos/display/output_configurator_unittest.cc b/chromeos/display/output_configurator_unittest.cc
index 28f0553..571df38 100644
--- a/chromeos/display/output_configurator_unittest.cc
+++ b/chromeos/display/output_configurator_unittest.cc
@@ -4,6 +4,7 @@
#include "chromeos/display/output_configurator.h"
+#include <cmath>
#include <cstdarg>
#include <map>
#include <string>
@@ -128,6 +129,11 @@ class TestDelegate : public OutputConfigurator::Delegate {
return actions;
}
+ const OutputConfigurator::CoordinateTransformation& get_ctm(
+ int touch_device_id) {
+ return ctms_[touch_device_id];
+ }
+
// OutputConfigurator::Delegate overrides:
virtual void InitXRandRExtension(int* event_base) OVERRIDE {
AppendAction(kInitXRandR);
@@ -171,6 +177,7 @@ class TestDelegate : public OutputConfigurator::Delegate {
int touch_device_id,
const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE {
AppendAction(GetCTMAction(touch_device_id, ctm));
+ ctms_[touch_device_id] = ctm;
}
virtual void SendProjectingStateToPowerManager(bool projecting) OVERRIDE {
AppendAction(projecting ? kProjectingOn : kProjectingOff);
@@ -207,6 +214,9 @@ class TestDelegate : public OutputConfigurator::Delegate {
std::map<RRMode, ModeDetails> modes_;
+ // Most-recently-configured transformation matrices, keyed by touch device ID.
+ std::map<int, OutputConfigurator::CoordinateTransformation> ctms_;
+
// Outputs to be returned by GetOutputs().
std::vector<OutputConfigurator::OutputSnapshot> outputs_;
@@ -1223,4 +1233,34 @@ TEST_F(OutputConfiguratorTest, OutputProtectionTwoClients) {
delegate_->GetActionsAndClear());
}
+TEST_F(OutputConfiguratorTest, CTMForMultiScreens) {
+ outputs_[0].touch_device_id = 1;
+ outputs_[1].touch_device_id = 2;
+
+ UpdateOutputs(2, false);
+ configurator_.Init(false);
+ state_controller_.set_state(STATE_DUAL_EXTENDED);
+ configurator_.Start(0);
+
+ const int kDualHeight =
+ kSmallModeHeight + OutputConfigurator::kVerticalGap + kBigModeHeight;
+ const int kDualWidth = kBigModeWidth;
+
+ OutputConfigurator::CoordinateTransformation ctm1 = delegate_->get_ctm(1);
+ OutputConfigurator::CoordinateTransformation ctm2 = delegate_->get_ctm(2);
+
+ EXPECT_EQ(kSmallModeHeight - 1, round((kDualHeight - 1) * ctm1.y_scale));
+ EXPECT_EQ(0, round((kDualHeight - 1) * ctm1.y_offset));
+
+ EXPECT_EQ(kBigModeHeight - 1, round((kDualHeight - 1) * ctm2.y_scale));
+ EXPECT_EQ(kSmallModeHeight + OutputConfigurator::kVerticalGap,
+ round((kDualHeight - 1) * ctm2.y_offset));
+
+ EXPECT_EQ(kSmallModeWidth - 1, round((kDualWidth - 1) * ctm1.x_scale));
+ EXPECT_EQ(0, round((kDualWidth - 1) * ctm1.x_offset));
+
+ EXPECT_EQ(kBigModeWidth - 1, round((kDualWidth - 1) * ctm2.x_scale));
+ EXPECT_EQ(0, round((kDualWidth - 1) * ctm2.x_offset));
+}
+
} // namespace chromeos