Chromium Code Reviews| 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 OnGetDisplays(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 DISALLOW_COPY_AND_ASSIGN(WindowManager); | |
| 93 }; | |
| 94 | |
| 35 class DemoWindow : public ui::PlatformWindowDelegate { | 95 class DemoWindow : public ui::PlatformWindowDelegate { |
| 36 public: | 96 public: |
| 37 DemoWindow() : widget_(gfx::kNullAcceleratedWidget) { | 97 DemoWindow(WindowManager* window_manager, |
| 38 int width = kTestWindowWidth; | 98 RendererFactory* renderer_factory, |
| 39 int height = kTestWindowHeight; | 99 const gfx::Rect& bounds) |
| 40 sscanf(base::CommandLine::ForCurrentProcess() | 100 : window_manager_(window_manager), |
| 41 ->GetSwitchValueASCII(kWindowSize) | 101 renderer_factory_(renderer_factory), |
| 42 .c_str(), | 102 widget_(gfx::kNullAcceleratedWidget), |
| 43 "%dx%d", &width, &height); | 103 weak_ptr_factory_(this) { |
| 44 | 104 platform_window_ = |
| 45 platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( | 105 ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds); |
| 46 this, gfx::Rect(width, height)); | |
| 47 } | 106 } |
| 48 ~DemoWindow() override {} | 107 ~DemoWindow() override {} |
| 49 | 108 |
| 50 gfx::AcceleratedWidget GetAcceleratedWidget() { | 109 gfx::AcceleratedWidget GetAcceleratedWidget() { |
| 51 // TODO(spang): We should start rendering asynchronously. | 110 // TODO(spang): We should start rendering asynchronously. |
| 52 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget) | 111 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget) |
| 53 << "Widget not available synchronously"; | 112 << "Widget not available synchronously"; |
| 54 return widget_; | 113 return widget_; |
| 55 } | 114 } |
| 56 | 115 |
| 57 gfx::Size GetSize() { return platform_window_->GetBounds().size(); } | 116 gfx::Size GetSize() { return platform_window_->GetBounds().size(); } |
| 58 | 117 |
| 59 void Start(const base::Closure& quit_closure) { | 118 void Start() { |
| 60 quit_closure_ = quit_closure; | 119 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 61 | 120 FROM_HERE, |
| 62 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableGpu) && | 121 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 } | 122 } |
| 85 | 123 |
| 86 void Quit() { | 124 void Quit() { |
| 87 StopAnimation(); | 125 StopAnimation(); |
| 88 quit_closure_.Run(); | 126 window_manager_->Quit(); |
| 89 } | 127 } |
| 90 | 128 |
| 91 // PlatformWindowDelegate: | 129 // PlatformWindowDelegate: |
| 92 void OnBoundsChanged(const gfx::Rect& new_bounds) override {} | 130 void OnBoundsChanged(const gfx::Rect& new_bounds) override {} |
| 93 void OnDamageRect(const gfx::Rect& damaged_region) override {} | 131 void OnDamageRect(const gfx::Rect& damaged_region) override {} |
| 94 void DispatchEvent(ui::Event* event) override { | 132 void DispatchEvent(ui::Event* event) override { |
| 95 if (event->IsKeyEvent() && | 133 if (event->IsKeyEvent() && |
| 96 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q) | 134 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q) |
| 97 Quit(); | 135 Quit(); |
| 98 } | 136 } |
| 99 void OnCloseRequest() override { Quit(); } | 137 void OnCloseRequest() override { Quit(); } |
| 100 void OnClosed() override {} | 138 void OnClosed() override {} |
| 101 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} | 139 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} |
| 102 void OnLostCapture() override {} | 140 void OnLostCapture() override {} |
| 103 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { | 141 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { |
| 104 DCHECK_NE(widget, gfx::kNullAcceleratedWidget); | 142 DCHECK_NE(widget, gfx::kNullAcceleratedWidget); |
| 105 widget_ = widget; | 143 widget_ = widget; |
| 106 } | 144 } |
| 107 void OnActivationChanged(bool active) override {} | 145 void OnActivationChanged(bool active) override {} |
| 108 | 146 |
| 109 private: | 147 private: |
| 148 // Since we pretend to have a GPU process, we should also pretend to | |
| 149 // initialize the GPU resources via a posted task. | |
| 150 void StartOnGpu() { | |
| 151 renderer_ = | |
| 152 renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize()); | |
| 153 if (renderer_->Initialize()) { | |
| 154 timer_.Start(FROM_HERE, | |
| 155 base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds), | |
| 156 renderer_.get(), &ui::Renderer::RenderFrame); | |
| 157 } | |
| 158 } | |
| 110 | 159 |
| 111 void StopAnimation() { timer_.Stop(); } | 160 void StopAnimation() { timer_.Stop(); } |
| 112 | 161 |
| 113 bool StartInProcessGpu() { return ui_thread_gpu_.Initialize(); } | 162 WindowManager* window_manager_; // Not owned. |
| 163 RendererFactory* renderer_factory_; // Not owned. | |
| 114 | 164 |
| 115 scoped_ptr<ui::Renderer> renderer_; | 165 scoped_ptr<ui::Renderer> renderer_; |
| 116 | 166 |
| 117 // Timer for animation. | 167 // Timer for animation. |
| 118 base::RepeatingTimer<ui::Renderer> timer_; | 168 base::RepeatingTimer<ui::Renderer> timer_; |
| 119 | 169 |
| 120 // Window-related state. | 170 // Window-related state. |
| 121 scoped_ptr<ui::PlatformWindow> platform_window_; | 171 scoped_ptr<ui::PlatformWindow> platform_window_; |
| 122 gfx::AcceleratedWidget widget_; | 172 gfx::AcceleratedWidget widget_; |
| 123 | 173 |
| 124 // Helper for applications that do GL on main thread. | 174 base::WeakPtrFactory<DemoWindow> weak_ptr_factory_; |
| 125 ui::UiThreadGpu ui_thread_gpu_; | |
| 126 | |
| 127 base::Closure quit_closure_; | |
| 128 | 175 |
| 129 DISALLOW_COPY_AND_ASSIGN(DemoWindow); | 176 DISALLOW_COPY_AND_ASSIGN(DemoWindow); |
| 130 }; | 177 }; |
| 131 | 178 |
| 179 /////////////////////////////////////////////////////////////////////////////// | |
| 180 // RendererFactory implementation: | |
| 181 | |
| 182 RendererFactory::RendererFactory() : type_(SOFTWARE) { | |
| 183 } | |
| 184 | |
| 185 RendererFactory::~RendererFactory() { | |
| 186 } | |
| 187 | |
| 188 bool RendererFactory::Initialize() { | |
| 189 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | |
| 190 if (!command_line->HasSwitch(kDisableGpu) && | |
| 191 gfx::GLSurface::InitializeOneOff() && ui_thread_gpu_.Initialize()) { | |
| 192 if (command_line->HasSwitch(switches::kOzoneUseSurfaceless)) { | |
| 193 type_ = SURFACELESS_GL; | |
| 194 } else { | |
| 195 type_ = GL; | |
| 196 } | |
| 197 } else { | |
| 198 type_ = SOFTWARE; | |
| 199 } | |
| 200 | |
| 201 return true; | |
| 202 } | |
| 203 | |
| 204 scoped_ptr<ui::Renderer> RendererFactory::CreateRenderer( | |
| 205 gfx::AcceleratedWidget widget, | |
| 206 const gfx::Size& size) { | |
| 207 switch (type_) { | |
| 208 case GL: | |
| 209 return scoped_ptr<ui::Renderer>(new ui::GlRenderer(widget, size)); | |
| 210 case SURFACELESS_GL: | |
| 211 return scoped_ptr<ui::Renderer>( | |
| 212 new ui::SurfacelessGlRenderer(widget, size, &buffer_factory_)); | |
| 213 case SOFTWARE: | |
| 214 return scoped_ptr<ui::Renderer>(new ui::SoftwareRenderer(widget, size)); | |
| 215 } | |
| 216 | |
| 217 return nullptr; | |
|
alexst (slow to review)
2015/02/11 15:36:05
Every switch case is handled, I don't think you ne
dnicoara
2015/02/11 16:46:37
The CrOS build complains without this.
| |
| 218 } | |
| 219 | |
| 220 /////////////////////////////////////////////////////////////////////////////// | |
| 221 // WindowManager implementation: | |
| 222 | |
| 223 WindowManager::WindowManager(const base::Closure& quit_closure) | |
| 224 : delegate_( | |
| 225 ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()), | |
| 226 quit_closure_(quit_closure) { | |
| 227 if (!renderer_factory_.Initialize()) | |
| 228 LOG(FATAL) << "Failed to initialize renderer factory"; | |
| 229 | |
| 230 if (delegate_) { | |
| 231 delegate_->AddObserver(this); | |
| 232 delegate_->Initialize(); | |
| 233 OnConfigurationChanged(); | |
| 234 } else { | |
| 235 LOG(WARNING) << "No display delegate; falling back to test window"; | |
| 236 int width = kTestWindowWidth; | |
| 237 int height = kTestWindowHeight; | |
| 238 sscanf(base::CommandLine::ForCurrentProcess() | |
| 239 ->GetSwitchValueASCII(kWindowSize) | |
| 240 .c_str(), | |
| 241 "%dx%d", &width, &height); | |
| 242 | |
| 243 DemoWindow* window = new DemoWindow(this, &renderer_factory_, | |
| 244 gfx::Rect(gfx::Size(width, height))); | |
| 245 window->Start(); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 WindowManager::~WindowManager() { | |
| 250 if (delegate_) | |
| 251 delegate_->RemoveObserver(this); | |
| 252 } | |
| 253 | |
| 254 void WindowManager::Quit() { | |
| 255 quit_closure_.Run(); | |
| 256 } | |
| 257 | |
| 258 void WindowManager::OnConfigurationChanged() { | |
| 259 delegate_->GrabServer(); | |
| 260 delegate_->GetDisplays( | |
| 261 base::Bind(&WindowManager::OnGetDisplays, base::Unretained(this))); | |
| 262 } | |
| 263 | |
| 264 void WindowManager::OnGetDisplays( | |
|
alexst (slow to review)
2015/02/11 15:36:05
OnDisplaysAquired or soemthing? OnGet.. feels odd
dnicoara
2015/02/11 16:46:37
Done.
| |
| 265 const std::vector<ui::DisplaySnapshot*>& displays) { | |
| 266 windows_.clear(); | |
| 267 | |
| 268 gfx::Point origin; | |
| 269 for (auto display : displays) { | |
| 270 if (!display->native_mode()) { | |
| 271 LOG(ERROR) << "Display " << display->display_id() | |
| 272 << " doesn't have a native mode"; | |
| 273 continue; | |
| 274 } | |
| 275 | |
| 276 delegate_->Configure( | |
| 277 *display, display->native_mode(), origin, | |
| 278 base::Bind(&WindowManager::OnDisplayConfigured, base::Unretained(this), | |
| 279 gfx::Rect(origin, display->native_mode()->size()))); | |
| 280 origin.Offset(display->native_mode()->size().width(), 0); | |
| 281 } | |
| 282 delegate_->UngrabServer(); | |
| 283 } | |
| 284 | |
| 285 void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) { | |
| 286 if (success) { | |
| 287 scoped_ptr<DemoWindow> window( | |
| 288 new DemoWindow(this, &renderer_factory_, bounds)); | |
| 289 window->Start(); | |
| 290 windows_.push_back(window.release()); | |
| 291 } else { | |
| 292 LOG(ERROR) << "Failed to configure display at " << bounds.ToString(); | |
| 293 } | |
| 294 } | |
| 295 | |
| 132 int main(int argc, char** argv) { | 296 int main(int argc, char** argv) { |
| 133 base::CommandLine::Init(argc, argv); | 297 base::CommandLine::Init(argc, argv); |
| 134 base::AtExitManager exit_manager; | 298 base::AtExitManager exit_manager; |
| 135 | 299 |
| 136 // Build UI thread message loop. This is used by platform | 300 // Build UI thread message loop. This is used by platform |
| 137 // implementations for event polling & running background tasks. | 301 // implementations for event polling & running background tasks. |
| 138 base::MessageLoopForUI message_loop; | 302 base::MessageLoopForUI message_loop; |
| 139 | 303 |
| 140 ui::OzonePlatform::InitializeForUI(); | 304 ui::OzonePlatform::InitializeForUI(); |
| 141 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() | 305 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() |
| 142 ->SetCurrentLayoutByName("us"); | 306 ->SetCurrentLayoutByName("us"); |
| 143 | 307 |
| 144 base::RunLoop run_loop; | 308 base::RunLoop run_loop; |
| 145 | 309 |
| 146 scoped_ptr<DemoWindow> window(new DemoWindow); | 310 WindowManager window_manager(run_loop.QuitClosure()); |
| 147 window->Start(run_loop.QuitClosure()); | |
| 148 | 311 |
| 149 run_loop.Run(); | 312 run_loop.Run(); |
| 150 | 313 |
| 151 return 0; | 314 return 0; |
| 152 } | 315 } |
| OLD | NEW |