OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/at_exit.h" | 5 #include "base/at_exit.h" |
6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
| 7 #include "base/memory/scoped_vector.h" |
7 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
8 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/thread_task_runner_handle.h" |
9 #include "base/timer/timer.h" | 11 #include "base/timer/timer.h" |
| 12 #include "ui/display/types/display_snapshot.h" |
| 13 #include "ui/display/types/native_display_delegate.h" |
| 14 #include "ui/display/types/native_display_observer.h" |
10 #include "ui/events/event.h" | 15 #include "ui/events/event.h" |
11 #include "ui/events/keycodes/dom3/dom_code.h" | 16 #include "ui/events/keycodes/dom3/dom_code.h" |
12 #include "ui/events/ozone/layout/keyboard_layout_engine.h" | 17 #include "ui/events/ozone/layout/keyboard_layout_engine.h" |
13 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" | 18 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" |
14 #include "ui/gfx/geometry/rect.h" | 19 #include "ui/gfx/geometry/rect.h" |
15 #include "ui/gfx/geometry/size.h" | 20 #include "ui/gfx/geometry/size.h" |
16 #include "ui/gl/gl_surface.h" | 21 #include "ui/gl/gl_surface.h" |
17 #include "ui/ozone/demo/gl_renderer.h" | 22 #include "ui/ozone/demo/gl_renderer.h" |
18 #include "ui/ozone/demo/software_renderer.h" | 23 #include "ui/ozone/demo/software_renderer.h" |
19 #include "ui/ozone/demo/surfaceless_gl_renderer.h" | 24 #include "ui/ozone/demo/surfaceless_gl_renderer.h" |
| 25 #include "ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h" |
20 #include "ui/ozone/public/ozone_platform.h" | 26 #include "ui/ozone/public/ozone_platform.h" |
21 #include "ui/ozone/public/ozone_switches.h" | 27 #include "ui/ozone/public/ozone_switches.h" |
22 #include "ui/ozone/public/ui_thread_gpu.h" | 28 #include "ui/ozone/public/ui_thread_gpu.h" |
23 #include "ui/platform_window/platform_window.h" | 29 #include "ui/platform_window/platform_window.h" |
24 #include "ui/platform_window/platform_window_delegate.h" | 30 #include "ui/platform_window/platform_window_delegate.h" |
25 | 31 |
26 const int kTestWindowWidth = 800; | 32 const int kTestWindowWidth = 800; |
27 const int kTestWindowHeight = 600; | 33 const int kTestWindowHeight = 600; |
28 | 34 |
29 const int kFrameDelayMilliseconds = 16; | 35 const int kFrameDelayMilliseconds = 16; |
30 | 36 |
31 const char kDisableGpu[] = "disable-gpu"; | 37 const char kDisableGpu[] = "disable-gpu"; |
32 | 38 |
33 const char kWindowSize[] = "window-size"; | 39 const char kWindowSize[] = "window-size"; |
34 | 40 |
| 41 class DemoWindow; |
| 42 |
| 43 class RendererFactory { |
| 44 public: |
| 45 enum RendererType { |
| 46 GL, |
| 47 SURFACELESS_GL, |
| 48 SOFTWARE, |
| 49 }; |
| 50 |
| 51 RendererFactory(); |
| 52 ~RendererFactory(); |
| 53 |
| 54 bool Initialize(); |
| 55 scoped_ptr<ui::Renderer> CreateRenderer(gfx::AcceleratedWidget widget, |
| 56 const gfx::Size& size); |
| 57 |
| 58 private: |
| 59 RendererType type_; |
| 60 |
| 61 // Helper for applications that do GL on main thread. |
| 62 ui::UiThreadGpu ui_thread_gpu_; |
| 63 |
| 64 // Used by the surfaceless renderers to allocate buffers. |
| 65 ui::GpuMemoryBufferFactoryOzoneNativeBuffer buffer_factory_; |
| 66 |
| 67 DISALLOW_COPY_AND_ASSIGN(RendererFactory); |
| 68 }; |
| 69 |
| 70 class WindowManager : public ui::NativeDisplayObserver { |
| 71 public: |
| 72 WindowManager(const base::Closure& quit_closure); |
| 73 ~WindowManager() override; |
| 74 |
| 75 void Quit(); |
| 76 |
| 77 void AddWindow(DemoWindow* window); |
| 78 void RemoveWindow(DemoWindow* window); |
| 79 |
| 80 private: |
| 81 void OnDisplaysAquired(const std::vector<ui::DisplaySnapshot*>& displays); |
| 82 void OnDisplayConfigured(const gfx::Rect& bounds, bool success); |
| 83 |
| 84 // ui::NativeDisplayDelegate: |
| 85 void OnConfigurationChanged() override; |
| 86 |
| 87 scoped_ptr<ui::NativeDisplayDelegate> delegate_; |
| 88 base::Closure quit_closure_; |
| 89 RendererFactory renderer_factory_; |
| 90 ScopedVector<DemoWindow> windows_; |
| 91 |
| 92 // Flags used to keep track of the current state of display configuration. |
| 93 // |
| 94 // True if configuring the displays. In this case a new display configuration |
| 95 // isn't started. |
| 96 bool is_configuring_; |
| 97 |
| 98 // If |is_configuring_| is true and another display configuration event |
| 99 // happens, the event is deferred. This is set to true and a display |
| 100 // configuration will be scheduled after the current one finishes. |
| 101 bool should_configure_; |
| 102 |
| 103 DISALLOW_COPY_AND_ASSIGN(WindowManager); |
| 104 }; |
| 105 |
35 class DemoWindow : public ui::PlatformWindowDelegate { | 106 class DemoWindow : public ui::PlatformWindowDelegate { |
36 public: | 107 public: |
37 DemoWindow() : widget_(gfx::kNullAcceleratedWidget) { | 108 DemoWindow(WindowManager* window_manager, |
38 int width = kTestWindowWidth; | 109 RendererFactory* renderer_factory, |
39 int height = kTestWindowHeight; | 110 const gfx::Rect& bounds) |
40 sscanf(base::CommandLine::ForCurrentProcess() | 111 : window_manager_(window_manager), |
41 ->GetSwitchValueASCII(kWindowSize) | 112 renderer_factory_(renderer_factory), |
42 .c_str(), | 113 widget_(gfx::kNullAcceleratedWidget), |
43 "%dx%d", &width, &height); | 114 weak_ptr_factory_(this) { |
44 | 115 platform_window_ = |
45 platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( | 116 ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds); |
46 this, gfx::Rect(width, height)); | |
47 } | 117 } |
48 ~DemoWindow() override {} | 118 ~DemoWindow() override {} |
49 | 119 |
50 gfx::AcceleratedWidget GetAcceleratedWidget() { | 120 gfx::AcceleratedWidget GetAcceleratedWidget() { |
51 // TODO(spang): We should start rendering asynchronously. | 121 // TODO(spang): We should start rendering asynchronously. |
52 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget) | 122 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget) |
53 << "Widget not available synchronously"; | 123 << "Widget not available synchronously"; |
54 return widget_; | 124 return widget_; |
55 } | 125 } |
56 | 126 |
57 gfx::Size GetSize() { return platform_window_->GetBounds().size(); } | 127 gfx::Size GetSize() { return platform_window_->GetBounds().size(); } |
58 | 128 |
59 void Start(const base::Closure& quit_closure) { | 129 void Start() { |
60 quit_closure_ = quit_closure; | 130 base::ThreadTaskRunnerHandle::Get()->PostTask( |
61 | 131 FROM_HERE, |
62 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableGpu) && | 132 base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr())); |
63 gfx::GLSurface::InitializeOneOff() && StartInProcessGpu()) { | |
64 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
65 switches::kOzoneUseSurfaceless)) { | |
66 renderer_.reset( | |
67 new ui::SurfacelessGlRenderer(GetAcceleratedWidget(), GetSize())); | |
68 } else { | |
69 renderer_.reset(new ui::GlRenderer(GetAcceleratedWidget(), GetSize())); | |
70 } | |
71 } else { | |
72 renderer_.reset( | |
73 new ui::SoftwareRenderer(GetAcceleratedWidget(), GetSize())); | |
74 } | |
75 | |
76 if (renderer_->Initialize()) { | |
77 timer_.Start(FROM_HERE, | |
78 base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds), | |
79 renderer_.get(), &ui::Renderer::RenderFrame); | |
80 } else { | |
81 LOG(ERROR) << "Failed to create drawing surface"; | |
82 Quit(); | |
83 } | |
84 } | 133 } |
85 | 134 |
86 void Quit() { | 135 void Quit() { |
87 StopAnimation(); | 136 StopAnimation(); |
88 quit_closure_.Run(); | 137 window_manager_->Quit(); |
89 } | 138 } |
90 | 139 |
91 // PlatformWindowDelegate: | 140 // PlatformWindowDelegate: |
92 void OnBoundsChanged(const gfx::Rect& new_bounds) override {} | 141 void OnBoundsChanged(const gfx::Rect& new_bounds) override {} |
93 void OnDamageRect(const gfx::Rect& damaged_region) override {} | 142 void OnDamageRect(const gfx::Rect& damaged_region) override {} |
94 void DispatchEvent(ui::Event* event) override { | 143 void DispatchEvent(ui::Event* event) override { |
95 if (event->IsKeyEvent() && | 144 if (event->IsKeyEvent() && |
96 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q) | 145 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q) |
97 Quit(); | 146 Quit(); |
98 } | 147 } |
99 void OnCloseRequest() override { Quit(); } | 148 void OnCloseRequest() override { Quit(); } |
100 void OnClosed() override {} | 149 void OnClosed() override {} |
101 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} | 150 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} |
102 void OnLostCapture() override {} | 151 void OnLostCapture() override {} |
103 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { | 152 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { |
104 DCHECK_NE(widget, gfx::kNullAcceleratedWidget); | 153 DCHECK_NE(widget, gfx::kNullAcceleratedWidget); |
105 widget_ = widget; | 154 widget_ = widget; |
106 } | 155 } |
107 void OnActivationChanged(bool active) override {} | 156 void OnActivationChanged(bool active) override {} |
108 | 157 |
109 private: | 158 private: |
| 159 // Since we pretend to have a GPU process, we should also pretend to |
| 160 // initialize the GPU resources via a posted task. |
| 161 void StartOnGpu() { |
| 162 renderer_ = |
| 163 renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize()); |
| 164 if (renderer_->Initialize()) { |
| 165 timer_.Start(FROM_HERE, |
| 166 base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds), |
| 167 renderer_.get(), &ui::Renderer::RenderFrame); |
| 168 } |
| 169 } |
110 | 170 |
111 void StopAnimation() { timer_.Stop(); } | 171 void StopAnimation() { timer_.Stop(); } |
112 | 172 |
113 bool StartInProcessGpu() { return ui_thread_gpu_.Initialize(); } | 173 WindowManager* window_manager_; // Not owned. |
| 174 RendererFactory* renderer_factory_; // Not owned. |
114 | 175 |
115 scoped_ptr<ui::Renderer> renderer_; | 176 scoped_ptr<ui::Renderer> renderer_; |
116 | 177 |
117 // Timer for animation. | 178 // Timer for animation. |
118 base::RepeatingTimer<ui::Renderer> timer_; | 179 base::RepeatingTimer<ui::Renderer> timer_; |
119 | 180 |
120 // Window-related state. | 181 // Window-related state. |
121 scoped_ptr<ui::PlatformWindow> platform_window_; | 182 scoped_ptr<ui::PlatformWindow> platform_window_; |
122 gfx::AcceleratedWidget widget_; | 183 gfx::AcceleratedWidget widget_; |
123 | 184 |
124 // Helper for applications that do GL on main thread. | 185 base::WeakPtrFactory<DemoWindow> weak_ptr_factory_; |
125 ui::UiThreadGpu ui_thread_gpu_; | |
126 | |
127 base::Closure quit_closure_; | |
128 | 186 |
129 DISALLOW_COPY_AND_ASSIGN(DemoWindow); | 187 DISALLOW_COPY_AND_ASSIGN(DemoWindow); |
130 }; | 188 }; |
131 | 189 |
| 190 /////////////////////////////////////////////////////////////////////////////// |
| 191 // RendererFactory implementation: |
| 192 |
| 193 RendererFactory::RendererFactory() : type_(SOFTWARE) { |
| 194 } |
| 195 |
| 196 RendererFactory::~RendererFactory() { |
| 197 } |
| 198 |
| 199 bool RendererFactory::Initialize() { |
| 200 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 201 if (!command_line->HasSwitch(kDisableGpu) && |
| 202 gfx::GLSurface::InitializeOneOff() && ui_thread_gpu_.Initialize()) { |
| 203 if (command_line->HasSwitch(switches::kOzoneUseSurfaceless)) { |
| 204 type_ = SURFACELESS_GL; |
| 205 } else { |
| 206 type_ = GL; |
| 207 } |
| 208 } else { |
| 209 type_ = SOFTWARE; |
| 210 } |
| 211 |
| 212 return true; |
| 213 } |
| 214 |
| 215 scoped_ptr<ui::Renderer> RendererFactory::CreateRenderer( |
| 216 gfx::AcceleratedWidget widget, |
| 217 const gfx::Size& size) { |
| 218 switch (type_) { |
| 219 case GL: |
| 220 return scoped_ptr<ui::Renderer>(new ui::GlRenderer(widget, size)); |
| 221 case SURFACELESS_GL: |
| 222 return scoped_ptr<ui::Renderer>( |
| 223 new ui::SurfacelessGlRenderer(widget, size, &buffer_factory_)); |
| 224 case SOFTWARE: |
| 225 return scoped_ptr<ui::Renderer>(new ui::SoftwareRenderer(widget, size)); |
| 226 } |
| 227 |
| 228 return nullptr; |
| 229 } |
| 230 |
| 231 /////////////////////////////////////////////////////////////////////////////// |
| 232 // WindowManager implementation: |
| 233 |
| 234 WindowManager::WindowManager(const base::Closure& quit_closure) |
| 235 : delegate_( |
| 236 ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()), |
| 237 quit_closure_(quit_closure), |
| 238 is_configuring_(false), |
| 239 should_configure_(false) { |
| 240 if (!renderer_factory_.Initialize()) |
| 241 LOG(FATAL) << "Failed to initialize renderer factory"; |
| 242 |
| 243 if (delegate_) { |
| 244 delegate_->AddObserver(this); |
| 245 delegate_->Initialize(); |
| 246 OnConfigurationChanged(); |
| 247 } else { |
| 248 LOG(WARNING) << "No display delegate; falling back to test window"; |
| 249 int width = kTestWindowWidth; |
| 250 int height = kTestWindowHeight; |
| 251 sscanf(base::CommandLine::ForCurrentProcess() |
| 252 ->GetSwitchValueASCII(kWindowSize) |
| 253 .c_str(), |
| 254 "%dx%d", &width, &height); |
| 255 |
| 256 DemoWindow* window = new DemoWindow(this, &renderer_factory_, |
| 257 gfx::Rect(gfx::Size(width, height))); |
| 258 window->Start(); |
| 259 } |
| 260 } |
| 261 |
| 262 WindowManager::~WindowManager() { |
| 263 if (delegate_) |
| 264 delegate_->RemoveObserver(this); |
| 265 } |
| 266 |
| 267 void WindowManager::Quit() { |
| 268 quit_closure_.Run(); |
| 269 } |
| 270 |
| 271 void WindowManager::OnConfigurationChanged() { |
| 272 if (is_configuring_) { |
| 273 should_configure_ = true; |
| 274 return; |
| 275 } |
| 276 |
| 277 is_configuring_ = true; |
| 278 delegate_->GrabServer(); |
| 279 delegate_->GetDisplays( |
| 280 base::Bind(&WindowManager::OnDisplaysAquired, base::Unretained(this))); |
| 281 } |
| 282 |
| 283 void WindowManager::OnDisplaysAquired( |
| 284 const std::vector<ui::DisplaySnapshot*>& displays) { |
| 285 windows_.clear(); |
| 286 |
| 287 gfx::Point origin; |
| 288 for (auto display : displays) { |
| 289 if (!display->native_mode()) { |
| 290 LOG(ERROR) << "Display " << display->display_id() |
| 291 << " doesn't have a native mode"; |
| 292 continue; |
| 293 } |
| 294 |
| 295 delegate_->Configure( |
| 296 *display, display->native_mode(), origin, |
| 297 base::Bind(&WindowManager::OnDisplayConfigured, base::Unretained(this), |
| 298 gfx::Rect(origin, display->native_mode()->size()))); |
| 299 origin.Offset(display->native_mode()->size().width(), 0); |
| 300 } |
| 301 delegate_->UngrabServer(); |
| 302 is_configuring_ = false; |
| 303 |
| 304 if (should_configure_) { |
| 305 should_configure_ = false; |
| 306 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 307 FROM_HERE, base::Bind(&WindowManager::OnConfigurationChanged, |
| 308 base::Unretained(this))); |
| 309 } |
| 310 } |
| 311 |
| 312 void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) { |
| 313 if (success) { |
| 314 scoped_ptr<DemoWindow> window( |
| 315 new DemoWindow(this, &renderer_factory_, bounds)); |
| 316 window->Start(); |
| 317 windows_.push_back(window.release()); |
| 318 } else { |
| 319 LOG(ERROR) << "Failed to configure display at " << bounds.ToString(); |
| 320 } |
| 321 } |
| 322 |
132 int main(int argc, char** argv) { | 323 int main(int argc, char** argv) { |
133 base::CommandLine::Init(argc, argv); | 324 base::CommandLine::Init(argc, argv); |
134 base::AtExitManager exit_manager; | 325 base::AtExitManager exit_manager; |
135 | 326 |
| 327 // Initialize logging so we can enable VLOG messages. |
| 328 logging::LoggingSettings settings; |
| 329 logging::InitLogging(settings); |
| 330 |
136 // Build UI thread message loop. This is used by platform | 331 // Build UI thread message loop. This is used by platform |
137 // implementations for event polling & running background tasks. | 332 // implementations for event polling & running background tasks. |
138 base::MessageLoopForUI message_loop; | 333 base::MessageLoopForUI message_loop; |
139 | 334 |
140 ui::OzonePlatform::InitializeForUI(); | 335 ui::OzonePlatform::InitializeForUI(); |
141 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() | 336 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() |
142 ->SetCurrentLayoutByName("us"); | 337 ->SetCurrentLayoutByName("us"); |
143 | 338 |
144 base::RunLoop run_loop; | 339 base::RunLoop run_loop; |
145 | 340 |
146 scoped_ptr<DemoWindow> window(new DemoWindow); | 341 WindowManager window_manager(run_loop.QuitClosure()); |
147 window->Start(run_loop.QuitClosure()); | |
148 | 342 |
149 run_loop.Run(); | 343 run_loop.Run(); |
150 | 344 |
151 return 0; | 345 return 0; |
152 } | 346 } |
OLD | NEW |