diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-08 05:55:02 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-08 05:55:02 +0000 |
commit | 6caf9606e791a6774f1150eff09c34dae9f552cc (patch) | |
tree | bb44f55c50d83c184bf733e68bbd494b66fdba2f /ash/display | |
parent | dba96ef37448812fd1cfde3c8714f3eda96de685 (diff) | |
download | chromium_src-6caf9606e791a6774f1150eff09c34dae9f552cc.zip chromium_src-6caf9606e791a6774f1150eff09c34dae9f552cc.tar.gz chromium_src-6caf9606e791a6774f1150eff09c34dae9f552cc.tar.bz2 |
Compositor reflector, which copies texture onto another compositor.
- added GL utility functions to create and copy texture for mirroring
- made sure we don't create two compositor for the same display.
- update the mirroring compositor size when the mirror window size
changed.
- fix a bug that was using int for display ID. changed the
initial value for faked display id so that we can catch
such error early in test.
BUG=239776
TEST=added new tests, plus manually on daisy (mirroring now works on daisy)
Review URL: https://chromiumcodereview.appspot.com/16232013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@205044 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/display')
-rw-r--r-- | ash/display/display_info.cc | 3 | ||||
-rw-r--r-- | ash/display/display_manager.cc | 6 | ||||
-rw-r--r-- | ash/display/display_manager_unittest.cc | 47 | ||||
-rw-r--r-- | ash/display/mirror_window_controller.cc | 40 | ||||
-rw-r--r-- | ash/display/mirror_window_controller.h | 17 |
5 files changed, 108 insertions, 5 deletions
diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc index fa72bdc..a3bed21 100644 --- a/ash/display/display_info.cc +++ b/ash/display/display_info.cc @@ -36,7 +36,8 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, const int kDefaultHostWindowWidth = 1366; const int kDefaultHostWindowHeight = 768; - static int64 synthesized_display_id = 1000; + // Use larger than max int to catch overflow early. + static int64 synthesized_display_id = 2200000000; #if defined(OS_WIN) gfx::Rect bounds(aura::RootWindowHost::GetNativeScreenSize()); diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index 28727a2..57441d7 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc @@ -441,7 +441,7 @@ void DisplayManager::UpdateDisplays( // the root window so that it matches the external display's // resolution. This is necessary in order for scaling to work while // mirrored. - int mirrored_display_id = gfx::Display::kInvalidDisplayID; + int64 mirrored_display_id = gfx::Display::kInvalidDisplayID; if (software_mirroring_enabled_ && new_display_info_list.size() == 2) mirrored_display_id = new_display_info_list[1].id(); @@ -560,6 +560,9 @@ void DisplayManager::UpdateDisplays( Shell::GetInstance()->screen()->NotifyDisplayRemoved(displays_.back()); displays_.pop_back(); } + // Create or delete the mirror window here to avoid creating two + // compositor on one display. + mirror_window_updater.reset(); for (std::vector<size_t>::iterator iter = added_display_indices.begin(); iter != added_display_indices.end(); ++iter) { Shell::GetInstance()->screen()->NotifyDisplayAdded(displays_[*iter]); @@ -568,7 +571,6 @@ void DisplayManager::UpdateDisplays( iter != changed_display_indices.end(); ++iter) { Shell::GetInstance()->screen()->NotifyBoundsChanged(displays_[*iter]); } - mirror_window_updater.reset(); display_controller->NotifyDisplayConfigurationChanged(); if (update_mouse_location) display_controller->EnsurePointerInDisplays(); diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index ce0c25d..8b1516b 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc @@ -876,15 +876,53 @@ TEST_F(DisplayManagerTest, MAYBE_UpdateMouseCursorAfterRotateZoom) { #define MAYBE_SoftwareMirroring SoftwareMirroring #endif +class TestDisplayObserver : public gfx::DisplayObserver { + public: + TestDisplayObserver() : changed_(false) {} + virtual ~TestDisplayObserver() {} + + // gfx::DisplayObserver overrides: + virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE { + } + virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE { + // Mirror window should already be delete before restoring + // the external dispay. + EXPECT_FALSE(test_api.GetRootWindow()); + changed_ = true; + } + virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE { + // Mirror window should not be created until the external display + // is removed. + EXPECT_FALSE(test_api.GetRootWindow()); + changed_ = true; + } + + bool changed_and_reset() { + bool changed = changed_; + changed_ = false; + return changed; + } + + private: + test::MirrorWindowTestApi test_api; + bool changed_; + + DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver); +}; + TEST_F(DisplayManagerTest, MAYBE_SoftwareMirroring) { UpdateDisplay("300x400,400x500"); test::MirrorWindowTestApi test_api; EXPECT_EQ(NULL, test_api.GetRootWindow()); + TestDisplayObserver display_observer; + Shell::GetScreen()->AddObserver(&display_observer); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); display_manager->SetSoftwareMirroring(true); display_manager->UpdateDisplays(); + EXPECT_TRUE(display_observer.changed_and_reset()); EXPECT_EQ(1U, display_manager->GetNumDisplays()); EXPECT_EQ("0,0 300x400", Shell::GetScreen()->GetPrimaryDisplay().bounds().ToString()); @@ -893,6 +931,7 @@ TEST_F(DisplayManagerTest, MAYBE_SoftwareMirroring) { EXPECT_TRUE(display_manager->IsMirrored()); display_manager->SetMirrorMode(false); + EXPECT_TRUE(display_observer.changed_and_reset()); EXPECT_EQ(NULL, test_api.GetRootWindow()); EXPECT_EQ(2U, display_manager->GetNumDisplays()); EXPECT_FALSE(display_manager->IsMirrored()); @@ -900,27 +939,35 @@ TEST_F(DisplayManagerTest, MAYBE_SoftwareMirroring) { // Make sure the mirror window has the pixel size of the // source display. display_manager->SetMirrorMode(true); + EXPECT_TRUE(display_observer.changed_and_reset()); UpdateDisplay("300x400@0.5,400x500"); + EXPECT_FALSE(display_observer.changed_and_reset()); EXPECT_EQ("300x400", test_api.GetRootWindow()->bounds().size().ToString()); EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString()); UpdateDisplay("310x410*2,400x500"); + EXPECT_FALSE(display_observer.changed_and_reset()); EXPECT_EQ("310x410", test_api.GetRootWindow()->bounds().size().ToString()); EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString()); UpdateDisplay("320x420/r,400x500"); + EXPECT_FALSE(display_observer.changed_and_reset()); EXPECT_EQ("320x420", test_api.GetRootWindow()->bounds().size().ToString()); EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString()); UpdateDisplay("330x440/r,400x500"); + EXPECT_FALSE(display_observer.changed_and_reset()); EXPECT_EQ("330x440", test_api.GetRootWindow()->bounds().size().ToString()); EXPECT_EQ("400x500", GetMirroredDisplay().size().ToString()); // Overscan insets are ignored. UpdateDisplay("400x600/o,600x800/o"); + EXPECT_FALSE(display_observer.changed_and_reset()); EXPECT_EQ("400x600", test_api.GetRootWindow()->bounds().size().ToString()); EXPECT_EQ("600x800", GetMirroredDisplay().size().ToString()); + + Shell::GetScreen()->RemoveObserver(&display_observer); } } // namespace internal diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc index 1b621e7..616cf4b 100644 --- a/ash/display/mirror_window_controller.cc +++ b/ash/display/mirror_window_controller.cc @@ -168,6 +168,7 @@ void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { // No need to remove RootWindowObserver because // the DisplayManager object outlives RootWindow objects. root_window_->AddRootWindowObserver(display_manager); + root_window_->AddRootWindowObserver(this); // TODO(oshima): TouchHUD is using idkey. root_window_->SetProperty(internal::kDisplayIdKey, display_info.id()); root_window_->Init(); @@ -179,6 +180,14 @@ void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { root_window_->ShowRootWindow(); // TODO(oshima): Start mirroring. + aura::Window* mirror_window = new aura::Window(NULL); + mirror_window->Init(ui::LAYER_TEXTURED); + root_window_->AddChild(mirror_window); + mirror_window->SetBounds(root_window_->bounds()); + mirror_window->Show(); + reflector_ = ui::ContextFactory::GetInstance()-> + CreateReflector(Shell::GetPrimaryRootWindow()->compositor(), + mirror_window->layer()); cursor_window_ = new aura::Window(cursor_window_delegate_.get()); cursor_window_->SetTransparent(true); @@ -213,11 +222,17 @@ void MirrorWindowController::UpdateWindow() { void MirrorWindowController::Close() { if (root_window_.get()) { + ui::ContextFactory::GetInstance()->RemoveReflector(reflector_); + reflector_ = NULL; root_window_->RemoveRootWindowObserver( Shell::GetInstance()->display_manager()); NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( aura::client::GetCaptureClient(root_window_.get())); delete capture_client; + + root_window_->RemoveRootWindowObserver( + Shell::GetInstance()->display_manager()); + root_window_->RemoveRootWindowObserver(this); root_window_.reset(); cursor_window_ = NULL; } @@ -264,5 +279,30 @@ void MirrorWindowController::SetMirroredCursorVisibility(bool visible) { visible ? cursor_window_->Show() : cursor_window_->Hide(); } +void MirrorWindowController::OnRootWindowResized( + const aura::RootWindow* root, + const gfx::Size& old_size) { + // Do not use |old_size| as it contains RootWindow's (but not host's) size, + // and this parameter wil be removed soon. + if (mirror_window_host_size_ == root->GetHostSize()) + return; + mirror_window_host_size_ = root->GetHostSize(); + reflector_->OnMirroringCompositorResized(); + + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( + display_manager->mirrored_display().id()); + const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( + Shell::GetScreen()->GetPrimaryDisplay().id()); + DCHECK(display_manager->mirrored_display().is_valid()); + scoped_ptr<aura::RootWindowTransformer> transformer( + internal::CreateRootWindowTransformerForMirroredDisplay( + source_display_info, + mirror_display_info)); + root_window_->SetRootWindowTransformer(transformer.Pass()); + + UpdateCursorLocation(); +} + } // namespace internal } // namespace ash diff --git a/ash/display/mirror_window_controller.h b/ash/display/mirror_window_controller.h index 3db86b3..76a8cfb 100644 --- a/ash/display/mirror_window_controller.h +++ b/ash/display/mirror_window_controller.h @@ -7,15 +7,22 @@ #include "ash/ash_export.h" #include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "ui/aura/root_window_observer.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" +#include "ui/gfx/size.h" namespace aura { class RootWindow; class Window; } +namespace ui { +class Reflector; +} + namespace ash { namespace test{ class MirrorWindowTestApi; @@ -28,10 +35,10 @@ class CursorWindowDelegate; // An object that copies the content of the primary root window to a // mirror window. This also draws a mouse cursor as the mouse cursor // is typically drawn by the window system. -class MirrorWindowController { +class MirrorWindowController : public aura::RootWindowObserver { public: MirrorWindowController(); - ~MirrorWindowController(); + virtual ~MirrorWindowController(); // Updates the root window's bounds using |display_info|. // Creates the new root window if one doesn't exist. @@ -50,6 +57,10 @@ class MirrorWindowController { void SetMirroredCursor(gfx::NativeCursor cursor); void SetMirroredCursorVisibility(bool visible); + // aura::RootWindowObserver overrides: + virtual void OnRootWindowResized(const aura::RootWindow* root, + const gfx::Size& old_size) OVERRIDE; + private: friend class test::MirrorWindowTestApi; @@ -58,6 +69,8 @@ class MirrorWindowController { scoped_ptr<aura::RootWindow> root_window_; scoped_ptr<CursorWindowDelegate> cursor_window_delegate_; gfx::Point hot_point_; + gfx::Size mirror_window_host_size_; + scoped_refptr<ui::Reflector> reflector_; DISALLOW_COPY_AND_ASSIGN(MirrorWindowController); }; |