summaryrefslogtreecommitdiffstats
path: root/ash/display
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-08 05:55:02 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-08 05:55:02 +0000
commit6caf9606e791a6774f1150eff09c34dae9f552cc (patch)
treebb44f55c50d83c184bf733e68bbd494b66fdba2f /ash/display
parentdba96ef37448812fd1cfde3c8714f3eda96de685 (diff)
downloadchromium_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.cc3
-rw-r--r--ash/display/display_manager.cc6
-rw-r--r--ash/display/display_manager_unittest.cc47
-rw-r--r--ash/display/mirror_window_controller.cc40
-rw-r--r--ash/display/mirror_window_controller.h17
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);
};