summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-12 22:35:53 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-12 22:35:53 +0000
commit2bd1fcf0d9c29762b83d73839b6f016b09d66d62 (patch)
treedcb821d7421ff931fedd797cbcd51b9a9f58263b
parent1f8ae227e655d43caf0089f4bcc4a90923171fad (diff)
downloadchromium_src-2bd1fcf0d9c29762b83d73839b6f016b09d66d62.zip
chromium_src-2bd1fcf0d9c29762b83d73839b6f016b09d66d62.tar.gz
chromium_src-2bd1fcf0d9c29762b83d73839b6f016b09d66d62.tar.bz2
Revert 250798 "Revert of Read compositor VSync information from ..."
Broke compilation. > Revert of Read compositor VSync information from platform, when possible (https://chromiumcodereview.appspot.com/138903025/) > > Reason for revert: > Reverting due to Windows crashes. See: > > http://crbug.com/343199 > > Original issue's description: > > Read compositor VSync information from platform, when possible > > > > The current query of VSync information through the GL context can be unreliable > > on platforms that can dynamically disable vblanks, or multi-monitor setups. > > Preferentially query the VSync information through the platform windowing > > system (presently: XRandR on CrOS) when possible. > > > > BUG=328953 > > TEST=local build, run on CrOS snow > > > > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=250250 > > TBR=oshima@chromium.org,piman@chromium.org,brianderson@chromium.org,sky@chromium.org,mukai@chromium.org > NOTREECHECKS=true > NOTRY=true > BUG=328953 > > Review URL: https://codereview.chromium.org/161413002 TBR=sheu@chromium.org Review URL: https://codereview.chromium.org/161743002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250810 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/display/display_change_observer_chromeos.cc71
-rw-r--r--ash/display/display_change_observer_chromeos.h4
-rw-r--r--ash/display/display_change_observer_chromeos_unittest.cc42
-rw-r--r--ash/display/display_controller.cc9
-rw-r--r--ash/display/display_info.cc71
-rw-r--r--ash/display/display_info.h45
-rw-r--r--ash/display/display_info_unittest.cc15
-rw-r--r--ash/display/display_manager.cc68
-rw-r--r--ash/display/display_manager.h10
-rw-r--r--ash/display/display_manager_unittest.cc82
-rw-r--r--ash/display/resolution_notification_controller_unittest.cc121
-rw-r--r--ash/wm/window_animations.cc4
-rw-r--r--cc/output/output_surface.cc13
-rw-r--r--cc/output/output_surface.h4
-rw-r--r--cc/output/output_surface_unittest.cc8
-rw-r--r--chrome/browser/chromeos/display/display_preferences.cc9
-rw-r--r--chrome/browser/chromeos/display/display_preferences_unittest.cc26
-rw-r--r--chrome/browser/ui/webui/options/chromeos/display_options_handler.cc40
-rw-r--r--content/browser/compositor/browser_compositor_output_surface.cc30
-rw-r--r--content/browser/compositor/browser_compositor_output_surface.h24
-rw-r--r--content/browser/compositor/browser_compositor_output_surface_proxy.cc2
-rw-r--r--content/browser/compositor/gpu_browser_compositor_output_surface.cc6
-rw-r--r--content/browser/compositor/gpu_browser_compositor_output_surface.h7
-rw-r--r--content/browser/compositor/gpu_process_transport_factory.cc6
-rw-r--r--content/browser/compositor/software_browser_compositor_output_surface.cc6
-rw-r--r--content/browser/compositor/software_browser_compositor_output_surface.h12
-rw-r--r--content/browser/compositor/software_browser_compositor_output_surface_unittest.cc6
-rw-r--r--content/browser/renderer_host/media/desktop_capture_device_aura.cc3
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.cc13
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura.h7
-rw-r--r--content/renderer/gpu/compositor_output_surface.cc10
-rw-r--r--content/renderer/gpu/compositor_output_surface.h4
-rw-r--r--ui/aura/bench/bench_main.cc5
-rw-r--r--ui/compositor/compositor.cc13
-rw-r--r--ui/compositor/compositor.gyp2
-rw-r--r--ui/compositor/compositor.h13
-rw-r--r--ui/compositor/compositor_observer.h5
-rw-r--r--ui/compositor/compositor_vsync_manager.cc63
-rw-r--r--ui/compositor/compositor_vsync_manager.h71
-rw-r--r--ui/compositor/layer_unittest.cc5
-rw-r--r--ui/compositor/test/draw_waiter_for_test.cc4
-rw-r--r--ui/compositor/test/draw_waiter_for_test.h3
-rw-r--r--ui/gl/sync_control_vsync_provider.cc27
43 files changed, 599 insertions, 390 deletions
diff --git a/ash/display/display_change_observer_chromeos.cc b/ash/display/display_change_observer_chromeos.cc
index b381d03..6343586 100644
--- a/ash/display/display_change_observer_chromeos.cc
+++ b/ash/display/display_change_observer_chromeos.cc
@@ -37,46 +37,52 @@ const unsigned int kHighDensityDPIThreshold = 160;
// 1 inch in mm.
const float kInchInMm = 25.4f;
-// Resolution list are sorted by the area in pixels and the larger
-// one comes first.
-struct ResolutionSorter {
- bool operator()(const Resolution& a, const Resolution& b) {
- return a.size.width() * a.size.height() > b.size.width() * b.size.height();
+// Display mode list is sorted by (in descending priority):
+// * the area in pixels.
+// * refresh rate.
+struct DisplayModeSorter {
+ bool operator()(const DisplayMode& a, const DisplayMode& b) {
+ if (a.size.GetArea() == b.size.GetArea())
+ return (a.refresh_rate > b.refresh_rate);
+ return (a.size.GetArea() > b.size.GetArea());
}
};
} // namespace
// static
-std::vector<Resolution> DisplayChangeObserver::GetResolutionList(
+std::vector<DisplayMode> DisplayChangeObserver::GetDisplayModeList(
const OutputConfigurator::OutputSnapshot& output) {
- typedef std::map<std::pair<int,int>, Resolution> ResolutionMap;
- ResolutionMap resolution_map;
+ typedef std::map<std::pair<int, int>, DisplayMode> DisplayModeMap;
+ DisplayModeMap display_mode_map;
for (std::map<RRMode, OutputConfigurator::ModeInfo>::const_iterator it =
output.mode_infos.begin(); it != output.mode_infos.end(); ++it) {
const OutputConfigurator::ModeInfo& mode_info = it->second;
const std::pair<int, int> size(mode_info.width, mode_info.height);
- const Resolution resolution(gfx::Size(mode_info.width, mode_info.height),
- mode_info.interlaced);
-
- // Add the resolution if it isn't already present and override interlaced
- // resolutions with non-interlaced ones.
- ResolutionMap::iterator resolution_it = resolution_map.find(size);
- if (resolution_it == resolution_map.end())
- resolution_map.insert(std::make_pair(size, resolution));
- else if (resolution_it->second.interlaced && !resolution.interlaced)
- resolution_it->second = resolution;
+ const DisplayMode display_mode(gfx::Size(mode_info.width, mode_info.height),
+ mode_info.refresh_rate,
+ mode_info.interlaced,
+ output.native_mode == it->first);
+
+ // Add the display mode if it isn't already present and override interlaced
+ // display modes with non-interlaced ones.
+ DisplayModeMap::iterator display_mode_it = display_mode_map.find(size);
+ if (display_mode_it == display_mode_map.end())
+ display_mode_map.insert(std::make_pair(size, display_mode));
+ else if (display_mode_it->second.interlaced && !display_mode.interlaced)
+ display_mode_it->second = display_mode;
}
- std::vector<Resolution> resolution_list;
- for (ResolutionMap::const_iterator iter = resolution_map.begin();
- iter != resolution_map.end();
+ std::vector<DisplayMode> display_mode_list;
+ for (DisplayModeMap::const_iterator iter = display_mode_map.begin();
+ iter != display_mode_map.end();
++iter) {
- resolution_list.push_back(iter->second);
+ display_mode_list.push_back(iter->second);
}
- std::sort(resolution_list.begin(), resolution_list.end(), ResolutionSorter());
- return resolution_list;
+ std::sort(
+ display_mode_list.begin(), display_mode_list.end(), DisplayModeSorter());
+ return display_mode_list;
}
DisplayChangeObserver::DisplayChangeObserver() {
@@ -105,14 +111,13 @@ ui::OutputState DisplayChangeObserver::GetStateForDisplayIds(
bool DisplayChangeObserver::GetResolutionForDisplayId(int64 display_id,
int* width,
int* height) const {
- gfx::Size resolution;
- if (!Shell::GetInstance()->display_manager()->
- GetSelectedResolutionForDisplayId(display_id, &resolution)) {
+ DisplayMode mode;
+ if (!Shell::GetInstance()->display_manager()->GetSelectedModeForDisplayId(
+ display_id, &mode))
return false;
- }
- *width = resolution.width();
- *height = resolution.height();
+ *width = mode.size.width();
+ *height = mode.size.height();
return true;
}
@@ -145,9 +150,7 @@ void DisplayChangeObserver::OnDisplayModeChanged(
gfx::Rect display_bounds(
output.x, output.y, mode_info->width, mode_info->height);
- std::vector<Resolution> resolutions;
- if (output.type != chromeos::OUTPUT_TYPE_INTERNAL)
- resolutions = GetResolutionList(output);
+ std::vector<DisplayMode> display_modes = GetDisplayModeList(output);
std::string name =
output.type == ui::OUTPUT_TYPE_INTERNAL
@@ -168,7 +171,7 @@ void DisplayChangeObserver::OnDisplayModeChanged(
displays.back().set_device_scale_factor(device_scale_factor);
displays.back().SetBounds(display_bounds);
displays.back().set_native(true);
- displays.back().set_resolutions(resolutions);
+ displays.back().set_display_modes(display_modes);
displays.back().set_touch_support(
output.touch_device_id == 0 ? gfx::Display::TOUCH_SUPPORT_UNAVAILABLE :
gfx::Display::TOUCH_SUPPORT_AVAILABLE);
diff --git a/ash/display/display_change_observer_chromeos.h b/ash/display/display_change_observer_chromeos.h
index b8d63e5..59c2dee 100644
--- a/ash/display/display_change_observer_chromeos.h
+++ b/ash/display/display_change_observer_chromeos.h
@@ -13,7 +13,7 @@
namespace ash {
namespace internal {
-struct Resolution;
+struct DisplayMode;
// An object that observes changes in display configuration and
// update DisplayManagers.
@@ -23,7 +23,7 @@ class DisplayChangeObserver
public ShellObserver {
public:
// Returns the resolution list.
- ASH_EXPORT static std::vector<Resolution> GetResolutionList(
+ ASH_EXPORT static std::vector<DisplayMode> GetDisplayModeList(
const chromeos::OutputConfigurator::OutputSnapshot& output);
DisplayChangeObserver();
diff --git a/ash/display/display_change_observer_chromeos_unittest.cc b/ash/display/display_change_observer_chromeos_unittest.cc
index 1f64be7..d99b154 100644
--- a/ash/display/display_change_observer_chromeos_unittest.cc
+++ b/ash/display/display_change_observer_chromeos_unittest.cc
@@ -15,7 +15,7 @@ typedef testing::Test DisplayChangeObserverTest;
namespace ash {
namespace internal {
-TEST_F(DisplayChangeObserverTest, GetResolutionList) {
+TEST_F(DisplayChangeObserverTest, GetDisplayModeList) {
OutputConfigurator::OutputSnapshot output;
output.mode_infos[11] = OutputConfigurator::ModeInfo(1920, 1200, false, 60);
@@ -40,31 +40,37 @@ TEST_F(DisplayChangeObserverTest, GetResolutionList) {
// Just one interlaced mode.
output.mode_infos[22] = OutputConfigurator::ModeInfo(640, 480, true, 60);
- std::vector<Resolution> resolutions =
- DisplayChangeObserver::GetResolutionList(output);
- ASSERT_EQ(6u, resolutions.size());
- EXPECT_EQ("1920x1200", resolutions[0].size.ToString());
- EXPECT_FALSE(resolutions[0].interlaced);
+ std::vector<DisplayMode> display_modes =
+ DisplayChangeObserver::GetDisplayModeList(output);
+ ASSERT_EQ(6u, display_modes.size());
+ EXPECT_EQ("1920x1200", display_modes[0].size.ToString());
+ EXPECT_FALSE(display_modes[0].interlaced);
+ EXPECT_EQ(display_modes[0].refresh_rate, 60);
- EXPECT_EQ("1920x1080", resolutions[1].size.ToString());
- EXPECT_FALSE(resolutions[1].interlaced);
+ EXPECT_EQ("1920x1080", display_modes[1].size.ToString());
+ EXPECT_FALSE(display_modes[1].interlaced);
+ EXPECT_EQ(display_modes[1].refresh_rate, 80);
- EXPECT_EQ("1280x720", resolutions[2].size.ToString());
- EXPECT_FALSE(resolutions[2].interlaced);
+ EXPECT_EQ("1280x720", display_modes[2].size.ToString());
+ EXPECT_FALSE(display_modes[2].interlaced);
+ EXPECT_EQ(display_modes[2].refresh_rate, 60);
- EXPECT_EQ("1024x768", resolutions[3].size.ToString());
- EXPECT_TRUE(resolutions[3].interlaced);
+ EXPECT_EQ("1024x768", display_modes[3].size.ToString());
+ EXPECT_TRUE(display_modes[3].interlaced);
+ EXPECT_EQ(display_modes[3].refresh_rate, 70);
- EXPECT_EQ("1024x600", resolutions[4].size.ToString());
- EXPECT_FALSE(resolutions[4].interlaced);
+ EXPECT_EQ("1024x600", display_modes[4].size.ToString());
+ EXPECT_FALSE(display_modes[4].interlaced);
+ EXPECT_EQ(display_modes[4].refresh_rate, 70);
- EXPECT_EQ("640x480", resolutions[5].size.ToString());
- EXPECT_TRUE(resolutions[5].interlaced);
+ EXPECT_EQ("640x480", display_modes[5].size.ToString());
+ EXPECT_TRUE(display_modes[5].interlaced);
+ EXPECT_EQ(display_modes[5].refresh_rate, 60);
// Outputs without any modes shouldn't cause a crash.
output.mode_infos.clear();
- resolutions = DisplayChangeObserver::GetResolutionList(output);
- EXPECT_EQ(0u, resolutions.size());
+ display_modes = DisplayChangeObserver::GetDisplayModeList(output);
+ EXPECT_EQ(0u, display_modes.size());
}
} // namespace internal
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index 0633d12..031a6b1 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -34,6 +34,7 @@
#include "ui/aura/window_property.h"
#include "ui/aura/window_tracker.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
@@ -120,6 +121,14 @@ void SetDisplayPropertiesOnHostWindow(aura::RootWindow* root,
scoped_ptr<aura::RootWindowTransformer> transformer(
internal::CreateRootWindowTransformerForDisplay(root->window(), display));
root->host()->SetRootWindowTransformer(transformer.Pass());
+
+ internal::DisplayMode mode;
+ if (GetDisplayManager()->GetSelectedModeForDisplayId(display.id(), &mode) &&
+ mode.refresh_rate > 0.0f) {
+ root->host()->compositor()->vsync_manager()->SetAuthoritativeVSyncInterval(
+ base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond /
+ mode.refresh_rate));
+ }
}
} // namespace
diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc
index d35f0fc0..17a1bc1 100644
--- a/ash/display/display_info.cc
+++ b/ash/display/display_info.cc
@@ -23,10 +23,17 @@
namespace ash {
namespace internal {
-Resolution::Resolution(const gfx::Size& size, bool interlaced)
+DisplayMode::DisplayMode()
+ : refresh_rate(0.0f), interlaced(false), native(false) {}
+
+DisplayMode::DisplayMode(const gfx::Size& size,
+ float refresh_rate,
+ bool interlaced,
+ bool native)
: size(size),
- interlaced(interlaced) {
-}
+ refresh_rate(refresh_rate),
+ interlaced(interlaced),
+ native(native) {}
// satic
DisplayInfo DisplayInfo::CreateFromSpec(const std::string& spec) {
@@ -104,17 +111,35 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
#endif
}
- std::vector<Resolution> resolutions;
+ std::vector<DisplayMode> display_modes;
if (Tokenize(main_spec, "#", &parts) == 2) {
+ size_t native_mode = 0;
+ int largest_area = -1;
+ float highest_refresh_rate = -1.0f;
main_spec = parts[0];
std::string resolution_list = parts[1];
count = Tokenize(resolution_list, "|", &parts);
for (size_t i = 0; i < count; ++i) {
std::string resolution = parts[i];
int width, height;
- if (sscanf(resolution.c_str(), "%dx%d", &width, &height) == 2)
- resolutions.push_back(Resolution(gfx::Size(width, height), false));
+ float refresh_rate = 0.0f;
+ if (sscanf(resolution.c_str(),
+ "%dx%d%%%f",
+ &width,
+ &height,
+ &refresh_rate) >= 2) {
+ if (width * height >= largest_area &&
+ refresh_rate > highest_refresh_rate) {
+ // Use mode with largest area and highest refresh rate as native.
+ largest_area = width * height;
+ highest_refresh_rate = refresh_rate;
+ native_mode = i;
+ }
+ display_modes.push_back(
+ DisplayMode(gfx::Size(width, height), refresh_rate, false, false));
+ }
}
+ display_modes[native_mode].native = true;
}
if (id == gfx::Display::kInvalidDisplayID)
@@ -125,7 +150,7 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
display_info.set_rotation(rotation);
display_info.set_configured_ui_scale(ui_scale);
display_info.SetBounds(bounds_in_native);
- display_info.set_resolutions(resolutions);
+ display_info.set_display_modes(display_modes);
// To test the overscan, it creates the default 5% overscan.
if (has_overscan) {
@@ -177,7 +202,7 @@ void DisplayInfo::Copy(const DisplayInfo& native_info) {
bounds_in_native_ = native_info.bounds_in_native_;
size_in_pixel_ = native_info.size_in_pixel_;
device_scale_factor_ = native_info.device_scale_factor_;
- resolutions_ = native_info.resolutions_;
+ display_modes_ = native_info.display_modes_;
touch_support_ = native_info.touch_support_;
// Copy overscan_insets_in_dip_ if it's not empty. This is for test
@@ -249,22 +274,28 @@ std::string DisplayInfo::ToString() const {
overscan_insets_in_dip_.ToString().c_str(),
rotation_degree,
configured_ui_scale_,
- touch_support_ == gfx::Display::TOUCH_SUPPORT_AVAILABLE ? "yes" :
- touch_support_ == gfx::Display::TOUCH_SUPPORT_UNAVAILABLE ? "no" :
- "unknown");
+ touch_support_ == gfx::Display::TOUCH_SUPPORT_AVAILABLE
+ ? "yes"
+ : touch_support_ == gfx::Display::TOUCH_SUPPORT_UNAVAILABLE
+ ? "no"
+ : "unknown");
}
std::string DisplayInfo::ToFullString() const {
- std::string resolutions_str;
- std::vector<Resolution>::const_iterator iter = resolutions_.begin();
- for (; iter != resolutions_.end(); ++iter) {
- if (!resolutions_str.empty())
- resolutions_str += ",";
- resolutions_str += iter->size.ToString();
- if (iter->interlaced)
- resolutions_str += "(i)";
+ std::string display_modes_str;
+ std::vector<DisplayMode>::const_iterator iter = display_modes_.begin();
+ for (; iter != display_modes_.end(); ++iter) {
+ if (!display_modes_str.empty())
+ display_modes_str += ",";
+ base::StringAppendF(&display_modes_str,
+ "(%dx%d@%f%c%s)",
+ iter->size.width(),
+ iter->size.height(),
+ iter->refresh_rate,
+ iter->interlaced ? 'I' : 'P',
+ iter->native ? "(N)" : "");
}
- return ToString() + ", resolutions=" + resolutions_str;
+ return ToString() + ", display_modes==" + display_modes_str;
}
} // namespace internal
diff --git a/ash/display/display_info.h b/ash/display/display_info.h
index ca6f270..ccb989a 100644
--- a/ash/display/display_info.h
+++ b/ash/display/display_info.h
@@ -16,13 +16,18 @@
namespace ash {
namespace internal {
-// A struct that represents the display's resolution and
-// interlaced info.
-struct ASH_EXPORT Resolution {
- Resolution(const gfx::Size& size, bool interlaced);
-
- gfx::Size size;
- bool interlaced;
+// A struct that represents the display's mode info.
+struct ASH_EXPORT DisplayMode {
+ DisplayMode();
+ DisplayMode(const gfx::Size& size,
+ float refresh_rate,
+ bool interlaced,
+ bool native);
+
+ gfx::Size size; // Physical pixel size of the display.
+ float refresh_rate; // Refresh rate of the display, in Hz.
+ bool interlaced; // True if mode is interlaced.
+ bool native; // True if mode is native mode of the display.
};
// DisplayInfo contains metadata for each display. This is used to
@@ -47,7 +52,7 @@ class ASH_EXPORT DisplayInfo {
// 270 degrees (to the 'l'eft).
// - ui-scale is floating value, e.g. @1.5 or @1.25.
// - |resolution list| is the list of size that is given in
- // |width x height| separated by '|'.
+ // |width x height [% refresh_rate]| separated by '|'.
//
// A couple of examples:
// "100x100"
@@ -63,9 +68,9 @@ class ASH_EXPORT DisplayInfo {
// "10+20-300x200/u@1.5"
// 300x200 window at 10,20 origin. 1x device scale factor.
// no overscan. flipped upside-down (180 degree) and 1.5 ui scale.
- // "200x100#300x200|200x100|100x100"
+ // "200x100#300x200|200x100%59.0|100x100%60"
// 200x100 window at 0,0 origin, with 3 possible resolutions,
- // 300x200, 200x100 and 100x100.
+ // 300x200, 200x100 at 59 Hz, and 100x100 at 60 Hz.
static DisplayInfo CreateFromSpec(const std::string& spec);
// Creates a DisplayInfo from string spec using given |id|.
@@ -142,19 +147,19 @@ class ASH_EXPORT DisplayInfo {
void set_native(bool native) { native_ = native; }
bool native() const { return native_; }
- const std::vector<Resolution>& resolutions() const {
- return resolutions_;
+ const std::vector<DisplayMode>& display_modes() const {
+ return display_modes_;
}
- void set_resolutions(std::vector<Resolution>& resolution) {
- resolutions_.swap(resolution);
+ void set_display_modes(std::vector<DisplayMode>& display_modes) {
+ display_modes_.swap(display_modes);
}
- // Returns a string representation of the DisplayInfo
- // excluding resolutions.
+ // Returns a string representation of the DisplayInfo, excluding display
+ // modes.
std::string ToString() const;
- // Returns a string representation of the DisplayInfo
- // including resolutions.
+ // Returns a string representation of the DisplayInfo, including display
+ // modes.
std::string ToFullString() const;
private:
@@ -188,8 +193,8 @@ class ASH_EXPORT DisplayInfo {
// True if this comes from native platform (DisplayChangeObserver).
bool native_;
- // The list of resolutions supported by this display.
- std::vector<Resolution> resolutions_;
+ // The list of modes supported by this display.
+ std::vector<DisplayMode> display_modes_;
};
} // namespace internal
diff --git a/ash/display/display_info_unittest.cc b/ash/display/display_info_unittest.cc
index 9faa0aa..50c06cf 100644
--- a/ash/display/display_info_unittest.cc
+++ b/ash/display/display_info_unittest.cc
@@ -45,12 +45,17 @@ TEST_F(DisplayInfoTest, CreateFromSpec) {
EXPECT_EQ(1.5f, info.configured_ui_scale());
info = DisplayInfo::CreateFromSpecWithID(
- "200x200#300x200|200x200|100x100", 10);
+ "200x200#300x200|200x200%59.9|100x100%60", 10);
EXPECT_EQ("0,0 200x200", info.bounds_in_native().ToString());
- EXPECT_EQ(3u, info.resolutions().size());
- EXPECT_EQ("300x200", info.resolutions()[0].size.ToString());
- EXPECT_EQ("200x200", info.resolutions()[1].size.ToString());
- EXPECT_EQ("100x100", info.resolutions()[2].size.ToString());
+ EXPECT_EQ(3u, info.display_modes().size());
+ EXPECT_EQ("300x200", info.display_modes()[0].size.ToString());
+ EXPECT_EQ("200x200", info.display_modes()[1].size.ToString());
+ EXPECT_EQ("100x100", info.display_modes()[2].size.ToString());
+ EXPECT_EQ(59.9f, info.display_modes()[1].refresh_rate);
+ EXPECT_EQ(60.0f, info.display_modes()[2].refresh_rate);
+ EXPECT_TRUE(info.display_modes()[0].native);
+ EXPECT_FALSE(info.display_modes()[1].native);
+ EXPECT_FALSE(info.display_modes()[2].native);
}
} // namespace internal
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index 6343aa0..b911bdd 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -78,11 +78,9 @@ struct DisplayInfoSortFunctor {
}
};
-struct ResolutionMatcher {
- explicit ResolutionMatcher(const gfx::Size& size) : size(size) {}
- bool operator()(const Resolution& resolution) {
- return resolution.size == size;
- }
+struct DisplayModeMatcher {
+ DisplayModeMatcher(const gfx::Size& size) : size(size) {}
+ bool operator()(const DisplayMode& mode) { return mode.size == size; }
gfx::Size size;
};
@@ -446,22 +444,16 @@ void DisplayManager::SetDisplayResolution(int64 display_id,
if (gfx::Display::InternalDisplayId() == display_id)
return;
const DisplayInfo& display_info = GetDisplayInfo(display_id);
- const std::vector<Resolution>& resolutions = display_info.resolutions();
- DCHECK_NE(0u, resolutions.size());
- std::vector<Resolution>::const_iterator iter =
- std::find_if(resolutions.begin(),
- resolutions.end(),
- ResolutionMatcher(resolution));
- if (iter == resolutions.end()) {
+ const std::vector<DisplayMode>& modes = display_info.display_modes();
+ DCHECK_NE(0u, modes.size());
+ std::vector<DisplayMode>::const_iterator iter =
+ std::find_if(modes.begin(), modes.end(), DisplayModeMatcher(resolution));
+ if (iter == modes.end()) {
LOG(WARNING) << "Unsupported resolution was requested:"
<< resolution.ToString();
return;
- } else if (iter == resolutions.begin()) {
- // The best resolution was set, so forget it.
- resolutions_.erase(display_id);
- } else {
- resolutions_[display_id] = resolution;
}
+ display_modes_[display_id] = *iter;
#if defined(OS_CHROMEOS) && defined(USE_X11)
if (base::SysInfo::IsRunningOnChromeOS())
Shell::GetInstance()->output_configurator()->ScheduleConfigureOutputs();
@@ -483,18 +475,20 @@ void DisplayManager::RegisterDisplayProperty(
display_info_[display_id].set_configured_ui_scale(ui_scale);
if (overscan_insets)
display_info_[display_id].SetOverscanInsets(*overscan_insets);
- if (!resolution_in_pixels.IsEmpty())
- resolutions_[display_id] = resolution_in_pixels;
+ if (!resolution_in_pixels.IsEmpty()) {
+ // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
+ // actual display info, is 60 Hz.
+ display_modes_[display_id] =
+ DisplayMode(resolution_in_pixels, 60.0f, false, false);
+ }
}
-bool DisplayManager::GetSelectedResolutionForDisplayId(
- int64 id,
- gfx::Size* resolution_out) const {
- std::map<int64, gfx::Size>::const_iterator iter =
- resolutions_.find(id);
- if (iter == resolutions_.end())
+bool DisplayManager::GetSelectedModeForDisplayId(int64 id,
+ DisplayMode* mode_out) const {
+ std::map<int64, DisplayMode>::const_iterator iter = display_modes_.find(id);
+ if (iter == display_modes_.end())
return false;
- *resolution_out = iter->second;
+ *mode_out = iter->second;
return true;
}
@@ -568,19 +562,19 @@ void DisplayManager::OnNativeDisplaysChanged(
}
const gfx::Size& resolution = iter->bounds_in_native().size();
- const std::vector<Resolution>& resolutions = iter->resolutions();
+ const std::vector<DisplayMode>& display_modes = iter->display_modes();
// This is empty the displays are initialized from InitFromCommandLine.
- if (!resolutions.size())
+ if (!display_modes.size())
continue;
- std::vector<Resolution>::const_iterator resolution_iter =
- std::find_if(resolutions.begin(),
- resolutions.end(),
- ResolutionMatcher(resolution));
+ std::vector<DisplayMode>::const_iterator display_modes_iter =
+ std::find_if(display_modes.begin(),
+ display_modes.end(),
+ DisplayModeMatcher(resolution));
// Update the actual resolution selected as the resolution request may fail.
- if (resolution_iter == resolutions.begin())
- resolutions_.erase(iter->id());
- else if (resolutions_.find(iter->id()) != resolutions_.end())
- resolutions_[iter->id()] = resolution;
+ if (display_modes_iter == display_modes.end())
+ display_modes_.erase(iter->id());
+ else if (display_modes_.find(iter->id()) != display_modes_.end())
+ display_modes_[iter->id()] = *display_modes_iter;
}
if (HasInternalDisplay() &&
!internal_display_connected &&
@@ -661,7 +655,7 @@ void DisplayManager::UpdateDisplays(
non_desktop_display_ =
CreateDisplayFromDisplayInfoById(non_desktop_display_id);
++new_info_iter;
- // Remove existing external dispaly if it is going to be used as
+ // Remove existing external display if it is going to be used as
// non desktop.
if (curr_iter != displays_.end() &&
curr_iter->id() == non_desktop_display_id) {
diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h
index 3450a5d..a397c89 100644
--- a/ash/display/display_manager.h
+++ b/ash/display/display_manager.h
@@ -176,9 +176,9 @@ class ASH_EXPORT DisplayManager
const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels);
- // Returns the display's selected resolution.
- bool GetSelectedResolutionForDisplayId(int64 display_id,
- gfx::Size* resolution_out) const;
+ // Returns the display's selected mode.
+ bool GetSelectedModeForDisplayId(int64 display_id,
+ DisplayMode* mode_out) const;
// Tells if the virtual resolution feature is enabled.
bool IsDisplayUIScalingEnabled() const;
@@ -340,8 +340,8 @@ private:
// The mapping from the display ID to its internal data.
std::map<int64, DisplayInfo> display_info_;
- // Selected resolutions in pixels for displays. Key is the displays' ID.
- std::map<int64, gfx::Size> resolutions_;
+ // Selected display modes for displays. Key is the displays' ID.
+ std::map<int64, DisplayMode> display_modes_;
// When set to true, the host window's resize event updates
// the display's size. This is set to true when running on
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 9300ccc8..5b43b1b 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -719,49 +719,60 @@ TEST_F(DisplayManagerTest, DontRememberBestResolution) {
int display_id = 1000;
DisplayInfo native_display_info =
CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500));
- std::vector<Resolution> resolutions;
- resolutions.push_back(Resolution(gfx::Size(1000, 500), false));
- resolutions.push_back(Resolution(gfx::Size(800, 300), false));
- resolutions.push_back(Resolution(gfx::Size(400, 500), false));
+ std::vector<DisplayMode> display_modes;
+ display_modes.push_back(
+ DisplayMode(gfx::Size(1000, 500), 58.0f, false, true));
+ display_modes.push_back(
+ DisplayMode(gfx::Size(800, 300), 59.0f, false, false));
+ display_modes.push_back(
+ DisplayMode(gfx::Size(400, 500), 60.0f, false, false));
- native_display_info.set_resolutions(resolutions);
+ native_display_info.set_display_modes(display_modes);
std::vector<DisplayInfo> display_info_list;
display_info_list.push_back(native_display_info);
display_manager()->OnNativeDisplaysChanged(display_info_list);
- gfx::Size selected;
- EXPECT_FALSE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
+ DisplayMode mode;
+ EXPECT_FALSE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
// Unsupported resolution.
display_manager()->SetDisplayResolution(display_id, gfx::Size(800, 4000));
- EXPECT_FALSE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
+ EXPECT_FALSE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
// Supported resolution.
display_manager()->SetDisplayResolution(display_id, gfx::Size(800, 300));
- EXPECT_TRUE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
- EXPECT_EQ("800x300", selected.ToString());
+ EXPECT_TRUE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
+ EXPECT_EQ("800x300", mode.size.ToString());
+ EXPECT_EQ(59.0f, mode.refresh_rate);
+ EXPECT_FALSE(mode.native);
// Best resolution.
display_manager()->SetDisplayResolution(display_id, gfx::Size(1000, 500));
- EXPECT_FALSE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
+ EXPECT_TRUE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
+ EXPECT_EQ("1000x500", mode.size.ToString());
+ EXPECT_EQ(58.0f, mode.refresh_rate);
+ EXPECT_TRUE(mode.native);
}
TEST_F(DisplayManagerTest, ResolutionFallback) {
int display_id = 1000;
DisplayInfo native_display_info =
CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500));
- std::vector<Resolution> resolutions;
- resolutions.push_back(Resolution(gfx::Size(1000, 500), false));
- resolutions.push_back(Resolution(gfx::Size(800, 300), false));
- resolutions.push_back(Resolution(gfx::Size(400, 500), false));
+ std::vector<DisplayMode> display_modes;
+ display_modes.push_back(
+ DisplayMode(gfx::Size(1000, 500), 58.0f, false, true));
+ display_modes.push_back(
+ DisplayMode(gfx::Size(800, 300), 59.0f, false, false));
+ display_modes.push_back(
+ DisplayMode(gfx::Size(400, 500), 60.0f, false, false));
- std::vector<Resolution> copy = resolutions;
- native_display_info.set_resolutions(copy);
+ std::vector<DisplayMode> copy = display_modes;
+ native_display_info.set_display_modes(copy);
std::vector<DisplayInfo> display_info_list;
display_info_list.push_back(native_display_info);
@@ -770,31 +781,36 @@ TEST_F(DisplayManagerTest, ResolutionFallback) {
display_manager()->SetDisplayResolution(display_id, gfx::Size(800, 300));
DisplayInfo new_native_display_info =
CreateDisplayInfo(display_id, gfx::Rect(0, 0, 400, 500));
- copy = resolutions;
- new_native_display_info.set_resolutions(copy);
+ copy = display_modes;
+ new_native_display_info.set_display_modes(copy);
std::vector<DisplayInfo> new_display_info_list;
new_display_info_list.push_back(new_native_display_info);
display_manager()->OnNativeDisplaysChanged(new_display_info_list);
- gfx::Size selected;
- EXPECT_TRUE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
- EXPECT_EQ("400x500", selected.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
+ EXPECT_EQ("400x500", mode.size.ToString());
+ EXPECT_EQ(60.0f, mode.refresh_rate);
+ EXPECT_FALSE(mode.native);
}
{
- // Best resolution should not be set.
+ // Best resolution should find itself on the resolutions list.
display_manager()->SetDisplayResolution(display_id, gfx::Size(800, 300));
DisplayInfo new_native_display_info =
CreateDisplayInfo(display_id, gfx::Rect(0, 0, 1000, 500));
- std::vector<Resolution> copy = resolutions;
- new_native_display_info.set_resolutions(copy);
+ std::vector<DisplayMode> copy = display_modes;
+ new_native_display_info.set_display_modes(copy);
std::vector<DisplayInfo> new_display_info_list;
new_display_info_list.push_back(new_native_display_info);
display_manager()->OnNativeDisplaysChanged(new_display_info_list);
- gfx::Size selected;
- EXPECT_FALSE(display_manager()->GetSelectedResolutionForDisplayId(
- display_id, &selected));
+ DisplayMode mode;
+ EXPECT_TRUE(
+ display_manager()->GetSelectedModeForDisplayId(display_id, &mode));
+ EXPECT_EQ("1000x500", mode.size.ToString());
+ EXPECT_EQ(58.0f, mode.refresh_rate);
+ EXPECT_TRUE(mode.native);
}
}
diff --git a/ash/display/resolution_notification_controller_unittest.cc b/ash/display/resolution_notification_controller_unittest.cc
index afbc4a7..e3b2740 100644
--- a/ash/display/resolution_notification_controller_unittest.cc
+++ b/ash/display/resolution_notification_controller_unittest.cc
@@ -157,7 +157,7 @@ TEST_F(ResolutionNotificationControllerTest, Basic) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
+ UpdateDisplay("300x300#300x300%57|200x200%58,250x250#250x250%59|200x200%60");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -171,25 +171,26 @@ TEST_F(ResolutionNotificationControllerTest, Basic) {
EXPECT_FALSE(controller()->DoesNotificationTimeout());
EXPECT_EQ(ExpectedNotificationMessage(id2, gfx::Size(200, 200)),
GetNotificationMessage());
- gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0, mode.refresh_rate);
// Click the revert button, which reverts to the best resolution.
ClickOnNotificationButton(0);
RunAllPendingInMessageLoop();
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(0, accept_count());
- EXPECT_FALSE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("250x250", mode.size.ToString());
+ EXPECT_EQ(59.0, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
+ UpdateDisplay("300x300#300x300%57|200x200%58,250x250#250x250%59|200x200%60");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -201,19 +202,19 @@ TEST_F(ResolutionNotificationControllerTest, ClickMeansAccept) {
ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
EXPECT_TRUE(IsNotificationVisible());
EXPECT_FALSE(controller()->DoesNotificationTimeout());
- gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0, mode.refresh_rate);
// Click the revert button, which reverts the resolution.
ClickOnNotification();
RunAllPendingInMessageLoop();
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(1, accept_count());
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
@@ -223,7 +224,7 @@ TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
- UpdateDisplay("300x300#300x300|200x200");
+ UpdateDisplay("300x300#300x300%59|200x200%60");
const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
EXPECT_TRUE(IsNotificationVisible());
@@ -234,13 +235,14 @@ TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
ClickOnNotificationButton(0);
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(1, accept_count());
- gfx::Size resolution;
- EXPECT_TRUE(display_manager->GetSelectedResolutionForDisplayId(
- display.id(), &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(
+ display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0f, mode.refresh_rate);
// In that case the second button is revert.
- UpdateDisplay("300x300#300x300|200x200");
+ UpdateDisplay("300x300#300x300%59|200x200%60");
SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
EXPECT_TRUE(IsNotificationVisible());
@@ -248,15 +250,17 @@ TEST_F(ResolutionNotificationControllerTest, AcceptButton) {
ClickOnNotificationButton(1);
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(1, accept_count());
- EXPECT_FALSE(display_manager->GetSelectedResolutionForDisplayId(
- display.id(), &resolution));
+ EXPECT_TRUE(
+ display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
+ EXPECT_EQ("300x300", mode.size.ToString());
+ EXPECT_EQ(59.0f, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, Close) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("100x100,150x150#150x150|200x200");
+ UpdateDisplay("100x100,150x150#150x150%59|200x200%60");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -268,10 +272,10 @@ TEST_F(ResolutionNotificationControllerTest, Close) {
ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
EXPECT_TRUE(IsNotificationVisible());
EXPECT_FALSE(controller()->DoesNotificationTimeout());
- gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0f, mode.refresh_rate);
// Close the notification (imitates clicking [x] button). Also verifies if
// this does not cause a crash. See crbug.com/271784
@@ -285,7 +289,7 @@ TEST_F(ResolutionNotificationControllerTest, Timeout) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200");
+ UpdateDisplay("300x300#300x300%59|200x200%60");
const gfx::Display& display = ash::Shell::GetScreen()->GetPrimaryDisplay();
SetDisplayResolutionAndNotify(display, gfx::Size(200, 200));
@@ -297,18 +301,21 @@ TEST_F(ResolutionNotificationControllerTest, Timeout) {
}
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(0, accept_count());
- gfx::Size resolution;
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
- EXPECT_FALSE(display_manager->GetSelectedResolutionForDisplayId(
- display.id(), &resolution));
+ DisplayMode mode;
+ EXPECT_TRUE(
+ display_manager->GetSelectedModeForDisplayId(display.id(), &mode));
+ EXPECT_EQ("300x300", mode.size.ToString());
+ EXPECT_EQ(59.0f, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200,200x200#250x250|200x200|100x100");
+ UpdateDisplay("300x300#300x300%56|200x200%57,"
+ "200x200#250x250%58|200x200%59|100x100%60");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -317,21 +324,23 @@ TEST_F(ResolutionNotificationControllerTest, DisplayDisconnected) {
ASSERT_TRUE(IsNotificationVisible());
// Disconnects the secondary display and verifies it doesn't cause crashes.
- UpdateDisplay("300x300#300x300|200x200");
+ UpdateDisplay("300x300#300x300%56|200x200%57");
RunAllPendingInMessageLoop();
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(0, accept_count());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(59.0f, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200,250x250#250x250|200x200");
+ UpdateDisplay("300x300#300x300%56|200x200%57,"
+ "250x250#250x250%58|200x200%59");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -340,34 +349,37 @@ TEST_F(ResolutionNotificationControllerTest, MultipleResolutionChange) {
ScreenUtil::GetSecondaryDisplay(), gfx::Size(200, 200));
EXPECT_TRUE(IsNotificationVisible());
EXPECT_FALSE(controller()->DoesNotificationTimeout());
- gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(59.0f, mode.refresh_rate);
// Invokes SetDisplayResolutionAndNotify during the previous notification is
// visible.
SetDisplayResolutionAndNotify(
ScreenUtil::GetSecondaryDisplay(), gfx::Size(250, 250));
- EXPECT_FALSE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("250x250", mode.size.ToString());
+ EXPECT_EQ(58.0f, mode.refresh_rate);
// Then, click the revert button. Although |old_resolution| for the second
// SetDisplayResolutionAndNotify is 200x200, it should revert to the original
- // size 150x150.
+ // size 250x250.
ClickOnNotificationButton(0);
RunAllPendingInMessageLoop();
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(0, accept_count());
- EXPECT_FALSE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("250x250", mode.size.ToString());
+ EXPECT_EQ(58.0f, mode.refresh_rate);
}
TEST_F(ResolutionNotificationControllerTest, Fallback) {
if (!SupportsMultipleDisplays())
return;
- UpdateDisplay("300x300#300x300|200x200,250x250#250x250|220x220|200x200");
+ UpdateDisplay("300x300#300x300%56|200x200%57,"
+ "250x250#250x250%58|220x220%59|200x200%60");
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
ash::internal::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager();
@@ -385,18 +397,19 @@ TEST_F(ResolutionNotificationControllerTest, Fallback) {
ExpectedFallbackNotificationMessage(
id2, gfx::Size(220, 220), gfx::Size(200, 200)),
GetNotificationMessage());
- gfx::Size resolution;
- EXPECT_TRUE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
- EXPECT_EQ("200x200", resolution.ToString());
+ DisplayMode mode;
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("200x200", mode.size.ToString());
+ EXPECT_EQ(60.0f, mode.refresh_rate);
// Click the revert button, which reverts to the best resolution.
ClickOnNotificationButton(0);
RunAllPendingInMessageLoop();
EXPECT_FALSE(IsNotificationVisible());
EXPECT_EQ(0, accept_count());
- EXPECT_FALSE(
- display_manager->GetSelectedResolutionForDisplayId(id2, &resolution));
+ EXPECT_TRUE(display_manager->GetSelectedModeForDisplayId(id2, &mode));
+ EXPECT_EQ("250x250", mode.size.ToString());
+ EXPECT_EQ(58.0f, mode.refresh_rate);
}
} // namespace internal
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc
index aad40c9..3a3e059 100644
--- a/ash/wm/window_animations.cc
+++ b/ash/wm/window_animations.cc
@@ -286,10 +286,6 @@ class CrossFadeObserver : public ui::CompositorObserver,
virtual void OnCompositingLockStateChanged(
ui::Compositor* compositor) OVERRIDE {
}
- virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {
- }
// aura::WindowObserver overrides:
virtual void OnWindowDestroying(aura::Window* window) OVERRIDE {
diff --git a/cc/output/output_surface.cc b/cc/output/output_surface.cc
index 9ba6dbb..87d6e84 100644
--- a/cc/output/output_surface.cc
+++ b/cc/output/output_surface.cc
@@ -117,11 +117,14 @@ void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
max_frames_pending_ = max_frames_pending;
}
-void OutputSurface::OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval) {
- TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged",
- "timebase", (timebase - base::TimeTicks()).InSecondsF(),
- "interval", interval.InSecondsF());
+void OutputSurface::CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ TRACE_EVENT2("cc",
+ "OutputSurface::CommitVSyncParameters",
+ "timebase",
+ (timebase - base::TimeTicks()).InSecondsF(),
+ "interval",
+ interval.InSecondsF());
if (frame_rate_controller_)
frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
}
diff --git a/cc/output/output_surface.h b/cc/output/output_surface.h
index 4478754..b751f06 100644
--- a/cc/output/output_surface.h
+++ b/cc/output/output_surface.h
@@ -159,8 +159,8 @@ class CC_EXPORT OutputSurface : public FrameRateControllerClient {
// The FrameRateController is deprecated.
// Platforms should move to native BeginImplFrames instead.
- void OnVSyncParametersChanged(base::TimeTicks timebase,
- base::TimeDelta interval);
+ void CommitVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
virtual void FrameRateControllerTick(bool throttled,
const BeginFrameArgs& args) OVERRIDE;
scoped_ptr<FrameRateController> frame_rate_controller_;
diff --git a/cc/output/output_surface_unittest.cc b/cc/output/output_surface_unittest.cc
index 73a76a3..b0220fb 100644
--- a/cc/output/output_surface_unittest.cc
+++ b/cc/output/output_surface_unittest.cc
@@ -46,9 +46,9 @@ class TestOutputSurface : public OutputSurface {
using OutputSurface::ReleaseGL;
- void OnVSyncParametersChangedForTesting(base::TimeTicks timebase,
- base::TimeDelta interval) {
- OnVSyncParametersChanged(timebase, interval);
+ void CommitVSyncParametersForTesting(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ CommitVSyncParameters(timebase, interval);
}
void BeginImplFrameForTesting() {
@@ -387,7 +387,7 @@ TEST(OutputSurfaceTest,
// We need to subtract an epsilon from Now() because some platforms have
// a slow clock.
- output_surface.OnVSyncParametersChangedForTesting(
+ output_surface.CommitVSyncParametersForTesting(
gfx::FrameTime::Now() - base::TimeDelta::FromSeconds(1), big_interval);
output_surface.SetMaxFramesPending(2);
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index ab7697b..b41f056 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -199,11 +199,12 @@ void StoreCurrentDisplayProperties() {
property_value->SetInteger(
"ui-scale",
static_cast<int>(info.configured_ui_scale() * 1000));
- gfx::Size resolution;
+ ash::internal::DisplayMode mode;
if (!display.IsInternal() &&
- display_manager->GetSelectedResolutionForDisplayId(id, &resolution)) {
- property_value->SetInteger("width", resolution.width());
- property_value->SetInteger("height", resolution.height());
+ display_manager->GetSelectedModeForDisplayId(id, &mode) &&
+ !mode.native) {
+ property_value->SetInteger("width", mode.size.width());
+ property_value->SetInteger("height", mode.size.height());
}
if (!info.overscan_insets_in_dip().empty())
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index 03d604e..3abfaa5 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -231,7 +231,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_EQ(1, rotation);
EXPECT_EQ(1250, ui_scale);
- // Internal display never registere the resolution.
+ // Internal display never registered the resolution.
int width = 0, height = 0;
EXPECT_FALSE(property->GetInteger("width", &width));
EXPECT_FALSE(property->GetInteger("height", &height));
@@ -271,11 +271,11 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id1), &property));
width = 0;
height = 0;
- // Internal dispaly shouldn't store its resolution.
+ // Internal display shouldn't store its resolution.
EXPECT_FALSE(property->GetInteger("width", &width));
EXPECT_FALSE(property->GetInteger("height", &height));
- // External dispaly's resolution must be stored this time because
+ // External display's resolution must be stored this time because
// it's not best.
EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
EXPECT_TRUE(property->GetInteger("width", &width));
@@ -320,7 +320,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_FALSE(property->GetInteger("width", &width));
EXPECT_FALSE(property->GetInteger("height", &height));
- // External dispaly's selected resolution must not change
+ // External display's selected resolution must not change
// by mirroring.
EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
EXPECT_TRUE(property->GetInteger("width", &width));
@@ -329,11 +329,8 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_EQ(200, height);
// Set new display's selected resolution.
- display_manager->RegisterDisplayProperty(id2 + 1,
- gfx::Display::ROTATE_0,
- 1.0f,
- NULL,
- gfx::Size(500, 400));
+ display_manager->RegisterDisplayProperty(
+ id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400));
UpdateDisplay("200x200*2, 600x500#600x500|500x400");
@@ -357,14 +354,11 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_FALSE(property->GetInteger("height", &height));
// Set yet another new display's selected resolution.
- display_manager->RegisterDisplayProperty(id2 + 1,
- gfx::Display::ROTATE_0,
- 1.0f,
- NULL,
- gfx::Size(500, 400));
+ display_manager->RegisterDisplayProperty(
+ id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400));
// Disconnect 2nd display first to generate new id for external display.
UpdateDisplay("200x200*2");
- UpdateDisplay("200x200*2, 500x400#600x500|500x400");
+ UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
// Update key as the 2nd display gets new id.
id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
key = base::Int64ToString(id1) + "," + base::Int64ToString(id2);
@@ -379,7 +373,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_TRUE(layout_value->GetString(kPrimaryIdKey, &primary_id_str));
EXPECT_EQ(base::Int64ToString(id1), primary_id_str);
- // External dispaly's selected resolution must be updated.
+ // External display's selected resolution must be updated.
EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
EXPECT_TRUE(property->GetInteger("width", &width));
EXPECT_TRUE(property->GetInteger("height", &height));
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index eff7e64..528dc20 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -54,9 +54,11 @@ int64 GetDisplayId(const base::ListValue* args) {
return display_id;
}
-bool CompareResolution(ash::internal::Resolution r1,
- ash::internal::Resolution r2) {
- return r1.size.GetArea() < r2.size.GetArea();
+bool CompareDisplayMode(ash::internal::DisplayMode d1,
+ ash::internal::DisplayMode d2) {
+ if (d1.size.GetArea() == d2.size.GetArea())
+ return d1.refresh_rate < d2.refresh_rate;
+ return d1.size.GetArea() < d2.size.GetArea();
}
} // namespace
@@ -187,7 +189,7 @@ void DisplayOptionsHandler::SendDisplayInfo(
js_display->SetBoolean("isInternal", display.IsInternal());
js_display->SetInteger("orientation",
static_cast<int>(display_info.rotation()));
- std::vector<ash::internal::Resolution> resolutions;
+ std::vector<ash::internal::DisplayMode> display_modes;
std::vector<float> ui_scales;
if (display.IsInternal()) {
ui_scales = DisplayManager::GetScalesForDisplay(display_info);
@@ -202,21 +204,21 @@ void DisplayOptionsHandler::SendDisplayInfo(
for (size_t i = 0; i < ui_scales.size(); ++i) {
gfx::SizeF new_size = base_size;
new_size.Scale(ui_scales[i]);
- resolutions.push_back(ash::internal::Resolution(
- gfx::ToFlooredSize(new_size), false /* interlaced */));
+ display_modes.push_back(ash::internal::DisplayMode(
+ gfx::ToFlooredSize(new_size), -1.0f, false, false));
}
} else {
- for (size_t i = 0; i < display_info.resolutions().size(); ++i)
- resolutions.push_back(display_info.resolutions()[i]);
+ for (size_t i = 0; i < display_info.display_modes().size(); ++i)
+ display_modes.push_back(display_info.display_modes()[i]);
}
- std::sort(resolutions.begin(), resolutions.end(), CompareResolution);
+ std::sort(display_modes.begin(), display_modes.end(), CompareDisplayMode);
base::ListValue* js_resolutions = new base::ListValue();
gfx::Size current_size = display_info.bounds_in_native().size();
gfx::Insets current_overscan = display_info.GetOverscanInsetsInPixel();
- for (size_t i = 0; i < resolutions.size(); ++i) {
+ for (size_t i = 0; i < display_modes.size(); ++i) {
base::DictionaryValue* resolution_info = new base::DictionaryValue();
- gfx::Size resolution = resolutions[i].size;
+ gfx::Size resolution = display_modes[i].size;
if (!ui_scales.empty()) {
resolution_info->SetDouble("scale", ui_scales[i]);
if (ui_scales[i] == 1.0f)
@@ -225,8 +227,8 @@ void DisplayOptionsHandler::SendDisplayInfo(
"selected", display_info.configured_ui_scale() == ui_scales[i]);
} else {
// Picks the largest one as the "best", which is the last element
- // because |resolutions| is sorted by its area.
- if (i == resolutions.size() - 1)
+ // because |display_modes| is sorted by its area.
+ if (i == display_modes.size() - 1)
resolution_info->SetBoolean("isBest", true);
resolution_info->SetBoolean("selected", (resolution == current_size));
resolution.Enlarge(
@@ -234,6 +236,10 @@ void DisplayOptionsHandler::SendDisplayInfo(
}
resolution_info->SetInteger("width", resolution.width());
resolution_info->SetInteger("height", resolution.height());
+ if (display_modes[i].refresh_rate > 0.0f) {
+ resolution_info->SetDouble("refreshRate",
+ display_modes[i].refresh_rate);
+ }
js_resolutions->Append(resolution_info);
}
js_display->Set("resolutions", js_resolutions);
@@ -352,11 +358,11 @@ void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) {
gfx::Size old_resolution = display_info.bounds_in_native().size();
bool has_new_resolution = false;
bool has_old_resolution = false;
- for (size_t i = 0; i < display_info.resolutions().size(); ++i) {
- ash::internal::Resolution resolution = display_info.resolutions()[i];
- if (resolution.size == new_resolution)
+ for (size_t i = 0; i < display_info.display_modes().size(); ++i) {
+ ash::internal::DisplayMode display_mode = display_info.display_modes()[i];
+ if (display_mode.size == new_resolution)
has_new_resolution = true;
- if (resolution.size == old_resolution)
+ if (display_mode.size == old_resolution)
has_old_resolution = true;
}
if (!has_new_resolution) {
diff --git a/content/browser/compositor/browser_compositor_output_surface.cc b/content/browser/compositor/browser_compositor_output_surface.cc
index 30ff485..ff09ab7 100644
--- a/content/browser/compositor/browser_compositor_output_surface.cc
+++ b/content/browser/compositor/browser_compositor_output_surface.cc
@@ -7,11 +7,9 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
-#include "base/message_loop/message_loop_proxy.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_switches.h"
namespace content {
@@ -20,13 +18,11 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor)
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager)
: OutputSurface(context_provider),
surface_id_(surface_id),
output_surface_map_(output_surface_map),
- compositor_message_loop_(compositor_message_loop),
- compositor_(compositor) {
+ vsync_manager_(vsync_manager) {
Initialize();
}
@@ -34,13 +30,11 @@ BrowserCompositorOutputSurface::BrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor)
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager)
: OutputSurface(software_device.Pass()),
surface_id_(surface_id),
output_surface_map_(output_surface_map),
- compositor_message_loop_(compositor_message_loop),
- compositor_(compositor) {
+ vsync_manager_(vsync_manager) {
Initialize();
}
@@ -49,6 +43,7 @@ BrowserCompositorOutputSurface::~BrowserCompositorOutputSurface() {
if (!HasClient())
return;
output_surface_map_->Remove(surface_id_);
+ vsync_manager_->RemoveObserver(this);
}
void BrowserCompositorOutputSurface::Initialize() {
@@ -77,6 +72,7 @@ bool BrowserCompositorOutputSurface::BindToClient(
output_surface_map_->AddWithID(this, surface_id_);
if (reflector_)
reflector_->OnSourceSurfaceReady(surface_id_);
+ vsync_manager_->AddObserver(this);
return true;
}
@@ -92,11 +88,15 @@ void BrowserCompositorOutputSurface::OnUpdateVSyncParameters(
base::TimeDelta interval) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
- OnVSyncParametersChanged(timebase, interval);
- compositor_message_loop_->PostTask(
- FROM_HERE,
- base::Bind(&ui::Compositor::OnUpdateVSyncParameters,
- compositor_, timebase, interval));
+ CommitVSyncParameters(timebase, interval);
+}
+
+void BrowserCompositorOutputSurface::OnUpdateVSyncParametersFromGpu(
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(HasClient());
+ vsync_manager_->UpdateVSyncParameters(timebase, interval);
}
void BrowserCompositorOutputSurface::SetReflector(ReflectorImpl* reflector) {
diff --git a/content/browser/compositor/browser_compositor_output_surface.h b/content/browser/compositor/browser_compositor_output_surface.h
index bf0e366..7c26b083 100644
--- a/content/browser/compositor/browser_compositor_output_surface.h
+++ b/content/browser/compositor/browser_compositor_output_surface.h
@@ -6,19 +6,15 @@
#define CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_OUTPUT_SURFACE_H_
#include "base/id_map.h"
-#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "cc/output/output_surface.h"
#include "content/common/content_export.h"
-
-namespace base { class MessageLoopProxy; }
+#include "ui/compositor/compositor_vsync_manager.h"
namespace cc {
class SoftwareOutputDevice;
}
-namespace ui { class Compositor; }
-
namespace content {
class ContextProviderCommandBuffer;
class ReflectorImpl;
@@ -26,6 +22,7 @@ class WebGraphicsContext3DCommandBufferImpl;
class CONTENT_EXPORT BrowserCompositorOutputSurface
: public cc::OutputSurface,
+ public ui::CompositorVSyncManager::Observer,
public base::NonThreadSafe {
public:
virtual ~BrowserCompositorOutputSurface();
@@ -34,8 +31,12 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE;
virtual void Reshape(const gfx::Size& size, float scale_factor) OVERRIDE;
- void OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval);
+ // ui::CompositorOutputSurface::Observer implementation.
+ virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) OVERRIDE;
+
+ void OnUpdateVSyncParametersFromGpu(base::TimeTicks tiembase,
+ base::TimeDelta interval);
void SetReflector(ReflectorImpl* reflector);
@@ -45,22 +46,19 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor);
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
// Constructor used by the software implementation.
BrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor);
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
int surface_id_;
IDMap<BrowserCompositorOutputSurface>* output_surface_map_;
- scoped_refptr<base::MessageLoopProxy> compositor_message_loop_;
- base::WeakPtr<ui::Compositor> compositor_;
+ scoped_refptr<ui::CompositorVSyncManager> vsync_manager_;
scoped_refptr<ReflectorImpl> reflector_;
private:
diff --git a/content/browser/compositor/browser_compositor_output_surface_proxy.cc b/content/browser/compositor/browser_compositor_output_surface_proxy.cc
index d95c9b0..27fe55a 100644
--- a/content/browser/compositor/browser_compositor_output_surface_proxy.cc
+++ b/content/browser/compositor/browser_compositor_output_surface_proxy.cc
@@ -53,6 +53,6 @@ BrowserCompositorOutputSurfaceProxy::OnUpdateVSyncParametersOnCompositorThread(
base::TimeDelta interval) {
BrowserCompositorOutputSurface* surface = surface_map_->Lookup(surface_id);
if (surface)
- surface->OnUpdateVSyncParameters(timebase, interval);
+ surface->OnUpdateVSyncParametersFromGpu(timebase, interval);
}
} // namespace content
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index 17c4780..32a43fd 100644
--- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -15,13 +15,11 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor)
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager)
: BrowserCompositorOutputSurface(context,
surface_id,
output_surface_map,
- compositor_message_loop,
- compositor) {}
+ vsync_manager) {}
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.h b/content/browser/compositor/gpu_browser_compositor_output_surface.h
index c677839..a773ad5 100644
--- a/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -7,6 +7,10 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
+namespace ui {
+class CompositorVSyncManager;
+}
+
namespace content {
// Adapts a WebGraphicsContext3DCommandBufferImpl into a
@@ -19,8 +23,7 @@ class GpuBrowserCompositorOutputSurface
const scoped_refptr<ContextProviderCommandBuffer>& context,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor);
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
virtual ~GpuBrowserCompositorOutputSurface();
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index d97fdc1..d72958b 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -217,8 +217,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
CreateSoftwareOutputDevice(compositor),
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,
- base::MessageLoopProxy::current().get(),
- compositor->AsWeakPtr()));
+ compositor->vsync_manager()));
return surface.PassAs<cc::OutputSurface>();
}
@@ -237,8 +236,7 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
context_provider,
per_compositor_data_[compositor]->surface_id,
&output_surface_map_,
- base::MessageLoopProxy::current().get(),
- compositor->AsWeakPtr()));
+ compositor->vsync_manager()));
if (data->reflector.get()) {
data->reflector->CreateSharedTexture();
data->reflector->AttachToOutputSurface(surface.get());
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.cc b/content/browser/compositor/software_browser_compositor_output_surface.cc
index 4767e22..369fe93 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.cc
+++ b/content/browser/compositor/software_browser_compositor_output_surface.cc
@@ -21,13 +21,11 @@ SoftwareBrowserCompositorOutputSurface::SoftwareBrowserCompositorOutputSurface(
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor)
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager)
: BrowserCompositorOutputSurface(software_device.Pass(),
surface_id,
output_surface_map,
- compositor_message_loop,
- compositor),
+ vsync_manager),
output_surface_proxy_(surface_proxy) {}
SoftwareBrowserCompositorOutputSurface::
diff --git a/content/browser/compositor/software_browser_compositor_output_surface.h b/content/browser/compositor/software_browser_compositor_output_surface.h
index 88bf9a9..788d9da 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface.h
+++ b/content/browser/compositor/software_browser_compositor_output_surface.h
@@ -8,16 +8,15 @@
#include "base/memory/weak_ptr.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/common/content_export.h"
-#include "ui/compositor/compositor.h"
-
-namespace base {
-class MessageLoopProxy;
-}
namespace cc {
class SoftwareOutputDevice;
}
+namespace ui {
+class CompositorVSyncManager;
+}
+
namespace content {
class BrowserCompositorOutputSurfaceProxy;
@@ -30,8 +29,7 @@ class CONTENT_EXPORT SoftwareBrowserCompositorOutputSurface
scoped_ptr<cc::SoftwareOutputDevice> software_device,
int surface_id,
IDMap<BrowserCompositorOutputSurface>* output_surface_map,
- base::MessageLoopProxy* compositor_message_loop,
- base::WeakPtr<ui::Compositor> compositor);
+ const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager);
virtual ~SoftwareBrowserCompositorOutputSurface();
diff --git a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
index 047346f..3f48d21 100644
--- a/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
+++ b/content/browser/compositor/software_browser_compositor_output_surface_unittest.cc
@@ -7,6 +7,7 @@
#include "content/browser/compositor/browser_compositor_output_surface_proxy.h"
#include "content/browser/compositor/software_browser_compositor_output_surface.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/compositor.h"
#include "ui/compositor/test/context_factories_for_test.h"
#include "ui/gfx/vsync_provider.h"
@@ -79,6 +80,8 @@ class SoftwareBrowserCompositorOutputSurfaceTest : public testing::Test {
SoftwareBrowserCompositorOutputSurfaceTest::
SoftwareBrowserCompositorOutputSurfaceTest() {
+ // |message_loop_| is not used, but the main thread still has to exist for the
+ // compositor to use.
message_loop_.reset(new base::MessageLoopForUI);
}
@@ -114,8 +117,7 @@ SoftwareBrowserCompositorOutputSurfaceTest::CreateSurface(
device.Pass(),
1,
&surface_map_,
- compositor_->GetCompositorMessageLoop(),
- compositor_->AsWeakPtr()));
+ compositor_->vsync_manager()));
}
TEST_F(SoftwareBrowserCompositorOutputSurfaceTest, NoVSyncProvider) {
diff --git a/content/browser/renderer_host/media/desktop_capture_device_aura.cc b/content/browser/renderer_host/media/desktop_capture_device_aura.cc
index 877ce82..5669bce 100644
--- a/content/browser/renderer_host/media/desktop_capture_device_aura.cc
+++ b/content/browser/renderer_host/media/desktop_capture_device_aura.cc
@@ -113,9 +113,6 @@ class DesktopVideoCaptureMachine
virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE {}
virtual void OnCompositingLockStateChanged(
ui::Compositor* compositor) OVERRIDE {}
- virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {}
private:
// Captures a frame.
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 38bae4a..1c66023 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -3229,7 +3229,6 @@ void RenderWidgetHostViewAura::OnCompositingLockStateChanged(
}
void RenderWidgetHostViewAura::OnUpdateVSyncParameters(
- ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) {
if (IsShowing()) {
@@ -3530,6 +3529,10 @@ void RenderWidgetHostViewAura::AddedToRootWindow() {
legacy_render_widget_host_HWND_->UpdateParent(
reinterpret_cast<HWND>(GetNativeViewId()));
#endif
+
+ ui::Compositor* compositor = GetCompositor();
+ if (compositor)
+ compositor->vsync_manager()->AddObserver(this);
}
void RenderWidgetHostViewAura::RemovingFromRootWindow() {
@@ -3553,8 +3556,12 @@ void RenderWidgetHostViewAura::RemovingFromRootWindow() {
RunOnCommitCallbacks();
resize_lock_.reset();
host_->WasResized();
- if (compositor && compositor->HasObserver(this))
- compositor->RemoveObserver(this);
+
+ if (compositor) {
+ if (compositor->HasObserver(this))
+ compositor->RemoveObserver(this);
+ compositor->vsync_manager()->RemoveObserver(this);
+ }
#if defined(OS_WIN)
// Update the legacy window's parent temporarily to the desktop window. It
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index 995aaf6..7c6605c 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -37,6 +37,7 @@
#include "ui/base/ime/text_input_client.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_observer.h"
+#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/gfx/display_observer.h"
#include "ui/gfx/rect.h"
#include "webkit/common/cursors/webcursor.h"
@@ -79,6 +80,7 @@ class ResizeLock;
class CONTENT_EXPORT RenderWidgetHostViewAura
: public RenderWidgetHostViewBase,
public ui::CompositorObserver,
+ public ui::CompositorVSyncManager::Observer,
public ui::TextInputClient,
public gfx::DisplayObserver,
public aura::RootWindowObserver,
@@ -372,8 +374,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
virtual void OnCompositingAborted(ui::Compositor* compositor) OVERRIDE;
virtual void OnCompositingLockStateChanged(
ui::Compositor* compositor) OVERRIDE;
- virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
+
+ // Overridden from ui::CompositorVSyncManager::Observer
+ virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) OVERRIDE;
private:
diff --git a/content/renderer/gpu/compositor_output_surface.cc b/content/renderer/gpu/compositor_output_surface.cc
index 7cb5199..1ddafda 100644
--- a/content/renderer/gpu/compositor_output_surface.cc
+++ b/content/renderer/gpu/compositor_output_surface.cc
@@ -138,7 +138,8 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
if (!HasClient())
return;
IPC_BEGIN_MESSAGE_MAP(CompositorOutputSurface, message)
- IPC_MESSAGE_HANDLER(ViewMsg_UpdateVSyncParameters, OnUpdateVSyncParameters);
+ IPC_MESSAGE_HANDLER(ViewMsg_UpdateVSyncParameters,
+ OnUpdateVSyncParametersFromBrowser);
IPC_MESSAGE_HANDLER(ViewMsg_SwapCompositorFrameAck, OnSwapAck);
IPC_MESSAGE_HANDLER(ViewMsg_ReclaimCompositorResources, OnReclaimResources);
#if defined(OS_ANDROID)
@@ -147,10 +148,11 @@ void CompositorOutputSurface::OnMessageReceived(const IPC::Message& message) {
IPC_END_MESSAGE_MAP()
}
-void CompositorOutputSurface::OnUpdateVSyncParameters(
- base::TimeTicks timebase, base::TimeDelta interval) {
+void CompositorOutputSurface::OnUpdateVSyncParametersFromBrowser(
+ base::TimeTicks timebase,
+ base::TimeDelta interval) {
DCHECK(CalledOnValidThread());
- OnVSyncParametersChanged(timebase, interval);
+ CommitVSyncParameters(timebase, interval);
}
#if defined(OS_ANDROID)
diff --git a/content/renderer/gpu/compositor_output_surface.h b/content/renderer/gpu/compositor_output_surface.h
index 7afaa51..62e159d 100644
--- a/content/renderer/gpu/compositor_output_surface.h
+++ b/content/renderer/gpu/compositor_output_surface.h
@@ -90,8 +90,8 @@ class CompositorOutputSurface
};
void OnMessageReceived(const IPC::Message& message);
- void OnUpdateVSyncParameters(
- base::TimeTicks timebase, base::TimeDelta interval);
+ void OnUpdateVSyncParametersFromBrowser(base::TimeTicks timebase,
+ base::TimeDelta interval);
#if defined(OS_ANDROID)
void OnBeginImplFrame(const cc::BeginFrameArgs& args);
#endif
diff --git a/ui/aura/bench/bench_main.cc b/ui/aura/bench/bench_main.cc
index 94a8f6f..4f59dd36 100644
--- a/ui/aura/bench/bench_main.cc
+++ b/ui/aura/bench/bench_main.cc
@@ -122,11 +122,6 @@ class BenchCompositorObserver : public ui::CompositorObserver {
virtual void OnCompositingLockStateChanged(
Compositor* compositor) OVERRIDE {}
- virtual void OnUpdateVSyncParameters(ui::Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {
- }
-
virtual void Draw() {}
int frames() const { return frames_; }
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
index e662533..7061599 100644
--- a/ui/compositor/compositor.cc
+++ b/ui/compositor/compositor.cc
@@ -27,6 +27,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/frame_time.h"
@@ -183,6 +184,7 @@ namespace ui {
Compositor::Compositor(gfx::AcceleratedWidget widget)
: root_layer_(NULL),
widget_(widget),
+ vsync_manager_(new CompositorVSyncManager()),
posted_swaps_(new PostedSwapQueue()),
device_scale_factor_(0.0f),
last_started_frame_(0),
@@ -420,6 +422,10 @@ void Compositor::SetBackgroundColor(SkColor color) {
ScheduleDraw();
}
+scoped_refptr<CompositorVSyncManager> Compositor::vsync_manager() const {
+ return vsync_manager_;
+}
+
void Compositor::AddObserver(CompositorObserver* observer) {
observer_list_.AddObserver(observer);
}
@@ -432,13 +438,6 @@ bool Compositor::HasObserver(CompositorObserver* observer) {
return observer_list_.HasObserver(observer);
}
-void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) {
- FOR_EACH_OBSERVER(CompositorObserver,
- observer_list_,
- OnUpdateVSyncParameters(this, timebase, interval));
-}
-
void Compositor::Layout() {
// We're sending damage that will be addressed during this composite
// cycle, so we don't need to schedule another composite to address it.
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp
index 33f01ee..e1bd763 100644
--- a/ui/compositor/compositor.gyp
+++ b/ui/compositor/compositor.gyp
@@ -27,6 +27,8 @@
'compositor.h',
'compositor_export.h',
'compositor_observer.h',
+ 'compositor_vsync_manager.cc',
+ 'compositor_vsync_manager.h',
'compositor_switches.cc',
'compositor_switches.h',
'debug_utils.cc',
diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
index 81363ba..84ed365 100644
--- a/ui/compositor/compositor.h
+++ b/ui/compositor/compositor.h
@@ -43,6 +43,7 @@ class Size;
namespace ui {
class Compositor;
+class CompositorVSyncManager;
class Layer;
class PostedSwapQueue;
class Reflector;
@@ -163,8 +164,7 @@ class COMPOSITOR_EXPORT CompositorLock
// view hierarchy.
class COMPOSITOR_EXPORT Compositor
: NON_EXPORTED_BASE(public cc::LayerTreeHostClient),
- NON_EXPORTED_BASE(public cc::LayerTreeHostSingleThreadClient),
- public base::SupportsWeakPtr<Compositor> {
+ NON_EXPORTED_BASE(public cc::LayerTreeHostSingleThreadClient) {
public:
explicit Compositor(gfx::AcceleratedWidget widget);
virtual ~Compositor();
@@ -222,6 +222,9 @@ class COMPOSITOR_EXPORT Compositor
// Returns the widget for this compositor.
gfx::AcceleratedWidget widget() const { return widget_; }
+ // Returns the vsync manager for this compositor.
+ scoped_refptr<CompositorVSyncManager> vsync_manager() const;
+
// Compositor does not own observers. It is the responsibility of the
// observer to remove itself when it is done observing.
void AddObserver(CompositorObserver* observer);
@@ -244,9 +247,6 @@ class COMPOSITOR_EXPORT Compositor
// Signals swap has aborted (e.g. lost context).
void OnSwapBuffersAborted();
- void OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval);
-
// LayerTreeHostClient implementation.
virtual void WillBeginMainFrame(int frame_id) OVERRIDE {}
virtual void DidBeginMainFrame() OVERRIDE {}
@@ -302,6 +302,9 @@ class COMPOSITOR_EXPORT Compositor
scoped_refptr<cc::Layer> root_web_layer_;
scoped_ptr<cc::LayerTreeHost> host_;
+ // The manager of vsync parameters for this compositor.
+ scoped_refptr<CompositorVSyncManager> vsync_manager_;
+
// Used to verify that we have at most one draw swap in flight.
scoped_ptr<PostedSwapQueue> posted_swaps_;
diff --git a/ui/compositor/compositor_observer.h b/ui/compositor/compositor_observer.h
index aced251..badc5b4 100644
--- a/ui/compositor/compositor_observer.h
+++ b/ui/compositor/compositor_observer.h
@@ -38,11 +38,6 @@ class COMPOSITOR_EXPORT CompositorObserver {
// Called when the compositor lock state changes.
virtual void OnCompositingLockStateChanged(Compositor* compositor) = 0;
- // Called when the compositor has received updated VSync parameters.
- virtual void OnUpdateVSyncParameters(Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) = 0;
-
protected:
virtual ~CompositorObserver() {}
};
diff --git a/ui/compositor/compositor_vsync_manager.cc b/ui/compositor/compositor_vsync_manager.cc
new file mode 100644
index 0000000..1a10d4a
--- /dev/null
+++ b/ui/compositor/compositor_vsync_manager.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/compositor/compositor_vsync_manager.h"
+
+namespace ui {
+
+CompositorVSyncManager::CompositorVSyncManager()
+ : observer_list_(new ObserverListThreadSafe<Observer>()),
+ authoritative_vsync_interval_(base::TimeDelta::FromSeconds(0)) {}
+
+CompositorVSyncManager::~CompositorVSyncManager() {}
+
+void CompositorVSyncManager::SetAuthoritativeVSyncInterval(
+ base::TimeDelta interval) {
+ base::TimeTicks timebase;
+ {
+ base::AutoLock lock(vsync_parameters_lock_);
+ timebase = last_timebase_;
+ authoritative_vsync_interval_ = interval;
+ last_interval_ = interval;
+ }
+ NotifyObservers(timebase, interval);
+}
+
+void CompositorVSyncManager::UpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ {
+ base::AutoLock lock(vsync_parameters_lock_);
+ if (authoritative_vsync_interval_ != base::TimeDelta::FromSeconds(0))
+ interval = authoritative_vsync_interval_;
+ last_timebase_ = timebase;
+ last_interval_ = interval;
+ }
+ NotifyObservers(timebase, interval);
+}
+
+void CompositorVSyncManager::AddObserver(Observer* observer) {
+ base::TimeTicks timebase;
+ base::TimeDelta interval;
+ {
+ base::AutoLock lock(vsync_parameters_lock_);
+ timebase = last_timebase_;
+ interval = last_interval_;
+ }
+ observer_list_->AddObserver(observer);
+ observer->OnUpdateVSyncParameters(timebase, interval);
+}
+
+void CompositorVSyncManager::RemoveObserver(Observer* observer) {
+ observer_list_->RemoveObserver(observer);
+}
+
+void CompositorVSyncManager::NotifyObservers(base::TimeTicks timebase,
+ base::TimeDelta interval) {
+ observer_list_->Notify(
+ &CompositorVSyncManager::Observer::OnUpdateVSyncParameters,
+ timebase,
+ interval);
+}
+
+} // namespace ui
diff --git a/ui/compositor/compositor_vsync_manager.h b/ui/compositor/compositor_vsync_manager.h
new file mode 100644
index 0000000..abfbad6
--- /dev/null
+++ b/ui/compositor/compositor_vsync_manager.h
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_
+#define UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/observer_list_threadsafe.h"
+#include "base/synchronization/lock.h"
+#include "base/time/time.h"
+#include "ui/compositor/compositor_export.h"
+
+namespace ui {
+
+// This class manages vsync parameters for a compositor. It merges updates of
+// the parameters from different sources and sends the merged updates to
+// observers which register to it. This class is explicitly synchronized and is
+// safe to use and update from any thread. Observers of the manager will be
+// notified on the thread they have registered from, and should be removed from
+// the same thread.
+class COMPOSITOR_EXPORT CompositorVSyncManager
+ : public base::RefCountedThreadSafe<CompositorVSyncManager> {
+ public:
+ class Observer {
+ public:
+ virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) = 0;
+ };
+
+ CompositorVSyncManager();
+
+ // The "authoritative" vsync interval, if provided, will override |interval|
+ // as reported by UpdateVSyncParameters() whenever it is called. This is
+ // typically the value reported by a more reliable source, e.g. the platform
+ // display configuration. In the particular case of ChromeOS -- this is the
+ // value queried through XRandR, which is more reliable than the value
+ // queried through the 3D context.
+ void SetAuthoritativeVSyncInterval(base::TimeDelta interval);
+
+ // The vsync parameters consist of |timebase|, which is the platform timestamp
+ // of the last vsync, and |interval|, which is the interval between vsyncs.
+ // |interval| may be overriden by SetAuthoritativeVSyncInterval() above.
+ void UpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval);
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ private:
+ friend class base::RefCountedThreadSafe<CompositorVSyncManager>;
+
+ ~CompositorVSyncManager();
+
+ void NotifyObservers(base::TimeTicks timebase, base::TimeDelta interval);
+
+ // List of observers.
+ scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_;
+
+ // Protects the cached vsync parameters below.
+ base::Lock vsync_parameters_lock_;
+ base::TimeTicks last_timebase_;
+ base::TimeDelta last_interval_;
+ base::TimeDelta authoritative_vsync_interval_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorVSyncManager);
+};
+
+} // namespace ui
+
+#endif // UI_COMPOSITOR_COMPOSITOR_VSYNC_MANAGER_H_
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 736f92a..a384f32 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -354,11 +354,6 @@ class TestCompositorObserver : public CompositorObserver {
virtual void OnCompositingLockStateChanged(Compositor* compositor) OVERRIDE {
}
- virtual void OnUpdateVSyncParameters(Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE {
- }
-
bool committed_;
bool started_;
bool ended_;
diff --git a/ui/compositor/test/draw_waiter_for_test.cc b/ui/compositor/test/draw_waiter_for_test.cc
index 8429675..c471a6f 100644
--- a/ui/compositor/test/draw_waiter_for_test.cc
+++ b/ui/compositor/test/draw_waiter_for_test.cc
@@ -50,8 +50,4 @@ void DrawWaiterForTest::OnCompositingAborted(Compositor* compositor) {}
void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) {}
-void DrawWaiterForTest::OnUpdateVSyncParameters(Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) {}
-
} // namespace ui
diff --git a/ui/compositor/test/draw_waiter_for_test.h b/ui/compositor/test/draw_waiter_for_test.h
index d191ec4..051c58f 100644
--- a/ui/compositor/test/draw_waiter_for_test.h
+++ b/ui/compositor/test/draw_waiter_for_test.h
@@ -38,9 +38,6 @@ class DrawWaiterForTest : public CompositorObserver {
virtual void OnCompositingEnded(Compositor* compositor) OVERRIDE;
virtual void OnCompositingAborted(Compositor* compositor) OVERRIDE;
virtual void OnCompositingLockStateChanged(Compositor* compositor) OVERRIDE;
- virtual void OnUpdateVSyncParameters(Compositor* compositor,
- base::TimeTicks timebase,
- base::TimeDelta interval) OVERRIDE;
scoped_ptr<base::RunLoop> wait_run_loop_;
diff --git a/ui/gl/sync_control_vsync_provider.cc b/ui/gl/sync_control_vsync_provider.cc
index 16b1e8a..66d3734 100644
--- a/ui/gl/sync_control_vsync_provider.cc
+++ b/ui/gl/sync_control_vsync_provider.cc
@@ -125,16 +125,23 @@ void SyncControlVSyncProvider::GetVSyncParameters(
if (relative_change < kRelativeIntervalDifferenceThreshold) {
if (new_interval.InMicroseconds() < kMinVsyncIntervalUs ||
new_interval.InMicroseconds() > kMaxVsyncIntervalUs) {
- LOG(FATAL) << "Calculated bogus refresh interval of "
- << new_interval.InMicroseconds() << " us. "
- << "Last time base of " << last_timebase_.ToInternalValue()
- << " us. "
- << "Current time base of " << timebase.ToInternalValue()
- << " us. "
- << "Last media stream count of "
- << last_media_stream_counter_ << ". "
- << "Current media stream count of " << media_stream_counter
- << ".";
+#if defined(USE_ASH)
+ // On ash platforms (ChromeOS essentially), the real refresh interval is
+ // queried from XRandR, regardless of the value calculated here, and
+ // this value is overriden by ui::CompositorVSyncManager. The log
+ // should not be fatal in this case. Reconsider all this when XRandR
+ // support is added to non-ash platforms.
+ // http://crbug.com/340851
+ LOG(ERROR)
+#else
+ LOG(FATAL)
+#endif // USE_ASH
+ << "Calculated bogus refresh interval="
+ << new_interval.InMicroseconds()
+ << " us., last_timebase_=" << last_timebase_.ToInternalValue()
+ << " us., timebase=" << timebase.ToInternalValue()
+ << " us., last_media_stream_counter_=" << last_media_stream_counter_
+ << ", media_stream_counter=" << media_stream_counter;
} else {
last_good_interval_ = new_interval;
}