Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / ozone / demo / ozone_demo.cc
blobc5284228659a80a50adfa184a8b973c13a5bc0f0
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
3 // found in the LICENSE file.
5 #include "base/at_exit.h"
6 #include "base/command_line.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/run_loop.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "ui/display/types/display_snapshot.h"
12 #include "ui/display/types/native_display_delegate.h"
13 #include "ui/display/types/native_display_observer.h"
14 #include "ui/events/event.h"
15 #include "ui/events/keycodes/dom/dom_code.h"
16 #include "ui/events/ozone/layout/keyboard_layout_engine.h"
17 #include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
18 #include "ui/gfx/geometry/rect.h"
19 #include "ui/gfx/geometry/size.h"
20 #include "ui/gl/gl_surface.h"
21 #include "ui/ozone/demo/gl_renderer.h"
22 #include "ui/ozone/demo/software_renderer.h"
23 #include "ui/ozone/demo/surfaceless_gl_renderer.h"
24 #include "ui/ozone/public/ozone_gpu_test_helper.h"
25 #include "ui/ozone/public/ozone_platform.h"
26 #include "ui/ozone/public/ozone_switches.h"
27 #include "ui/platform_window/platform_window.h"
28 #include "ui/platform_window/platform_window_delegate.h"
30 const int kTestWindowWidth = 800;
31 const int kTestWindowHeight = 600;
33 const char kDisableGpu[] = "disable-gpu";
35 const char kDisableSurfaceless[] = "disable-surfaceless";
37 const char kWindowSize[] = "window-size";
39 class DemoWindow;
41 scoped_refptr<gfx::GLSurface> CreateGLSurface(gfx::AcceleratedWidget widget) {
42 scoped_refptr<gfx::GLSurface> surface;
43 if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableSurfaceless))
44 surface = gfx::GLSurface::CreateSurfacelessViewGLSurface(widget);
45 if (!surface)
46 surface = gfx::GLSurface::CreateViewGLSurface(widget);
47 return surface;
50 class RendererFactory {
51 public:
52 enum RendererType {
53 GL,
54 SOFTWARE,
57 RendererFactory();
58 ~RendererFactory();
60 bool Initialize();
61 scoped_ptr<ui::Renderer> CreateRenderer(gfx::AcceleratedWidget widget,
62 const gfx::Size& size);
64 private:
65 RendererType type_ = SOFTWARE;
67 // Helper for applications that do GL on main thread.
68 ui::OzoneGpuTestHelper gpu_helper_;
70 DISALLOW_COPY_AND_ASSIGN(RendererFactory);
73 class WindowManager : public ui::NativeDisplayObserver {
74 public:
75 WindowManager(const base::Closure& quit_closure);
76 ~WindowManager() override;
78 void Quit();
80 void AddWindow(DemoWindow* window);
81 void RemoveWindow(DemoWindow* window);
83 private:
84 void OnDisplaysAquired(const std::vector<ui::DisplaySnapshot*>& displays);
85 void OnDisplayConfigured(const gfx::Rect& bounds, bool success);
87 // ui::NativeDisplayDelegate:
88 void OnConfigurationChanged() override;
90 scoped_ptr<ui::NativeDisplayDelegate> delegate_;
91 base::Closure quit_closure_;
92 RendererFactory renderer_factory_;
93 ScopedVector<DemoWindow> windows_;
95 // Flags used to keep track of the current state of display configuration.
97 // True if configuring the displays. In this case a new display configuration
98 // isn't started.
99 bool is_configuring_ = false;
101 // If |is_configuring_| is true and another display configuration event
102 // happens, the event is deferred. This is set to true and a display
103 // configuration will be scheduled after the current one finishes.
104 bool should_configure_ = false;
106 DISALLOW_COPY_AND_ASSIGN(WindowManager);
109 class DemoWindow : public ui::PlatformWindowDelegate {
110 public:
111 DemoWindow(WindowManager* window_manager,
112 RendererFactory* renderer_factory,
113 const gfx::Rect& bounds)
114 : window_manager_(window_manager),
115 renderer_factory_(renderer_factory),
116 weak_ptr_factory_(this) {
117 platform_window_ =
118 ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds);
120 ~DemoWindow() override {}
122 gfx::AcceleratedWidget GetAcceleratedWidget() {
123 // TODO(spang): We should start rendering asynchronously.
124 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget)
125 << "Widget not available synchronously";
126 return widget_;
129 gfx::Size GetSize() { return platform_window_->GetBounds().size(); }
131 void Start() {
132 base::ThreadTaskRunnerHandle::Get()->PostTask(
133 FROM_HERE,
134 base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr()));
137 void Quit() {
138 window_manager_->Quit();
141 // PlatformWindowDelegate:
142 void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
143 void OnDamageRect(const gfx::Rect& damaged_region) override {}
144 void DispatchEvent(ui::Event* event) override {
145 if (event->IsKeyEvent() &&
146 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q)
147 Quit();
149 void OnCloseRequest() override { Quit(); }
150 void OnClosed() override {}
151 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
152 void OnLostCapture() override {}
153 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget,
154 float device_pixel_ratio) override {
155 DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
156 widget_ = widget;
158 void OnActivationChanged(bool active) override {}
160 private:
161 // Since we pretend to have a GPU process, we should also pretend to
162 // initialize the GPU resources via a posted task.
163 void StartOnGpu() {
164 renderer_ =
165 renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize());
166 renderer_->Initialize();
169 WindowManager* window_manager_; // Not owned.
170 RendererFactory* renderer_factory_; // Not owned.
172 scoped_ptr<ui::Renderer> renderer_;
174 // Window-related state.
175 scoped_ptr<ui::PlatformWindow> platform_window_;
176 gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
178 base::WeakPtrFactory<DemoWindow> weak_ptr_factory_;
180 DISALLOW_COPY_AND_ASSIGN(DemoWindow);
183 ///////////////////////////////////////////////////////////////////////////////
184 // RendererFactory implementation:
186 RendererFactory::RendererFactory() {
189 RendererFactory::~RendererFactory() {
192 bool RendererFactory::Initialize() {
193 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
194 if (!command_line->HasSwitch(kDisableGpu) &&
195 gfx::GLSurface::InitializeOneOff() &&
196 gpu_helper_.Initialize(base::ThreadTaskRunnerHandle::Get(),
197 base::ThreadTaskRunnerHandle::Get())) {
198 type_ = GL;
199 } else {
200 type_ = SOFTWARE;
203 return true;
206 scoped_ptr<ui::Renderer> RendererFactory::CreateRenderer(
207 gfx::AcceleratedWidget widget,
208 const gfx::Size& size) {
209 switch (type_) {
210 case GL: {
211 scoped_refptr<gfx::GLSurface> surface = CreateGLSurface(widget);
212 if (!surface)
213 LOG(FATAL) << "Failed to create GL surface";
214 if (surface->IsSurfaceless())
215 return make_scoped_ptr(
216 new ui::SurfacelessGlRenderer(widget, surface, size));
217 else
218 return make_scoped_ptr(new ui::GlRenderer(widget, surface, size));
220 case SOFTWARE:
221 return make_scoped_ptr(new ui::SoftwareRenderer(widget, size));
224 return nullptr;
227 ///////////////////////////////////////////////////////////////////////////////
228 // WindowManager implementation:
230 WindowManager::WindowManager(const base::Closure& quit_closure)
231 : delegate_(
232 ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()),
233 quit_closure_(quit_closure) {
234 if (!renderer_factory_.Initialize())
235 LOG(FATAL) << "Failed to initialize renderer factory";
237 if (delegate_) {
238 delegate_->AddObserver(this);
239 delegate_->Initialize();
240 OnConfigurationChanged();
241 } else {
242 LOG(WARNING) << "No display delegate; falling back to test window";
243 int width = kTestWindowWidth;
244 int height = kTestWindowHeight;
245 sscanf(base::CommandLine::ForCurrentProcess()
246 ->GetSwitchValueASCII(kWindowSize)
247 .c_str(),
248 "%dx%d", &width, &height);
250 DemoWindow* window = new DemoWindow(this, &renderer_factory_,
251 gfx::Rect(gfx::Size(width, height)));
252 window->Start();
256 WindowManager::~WindowManager() {
257 if (delegate_)
258 delegate_->RemoveObserver(this);
261 void WindowManager::Quit() {
262 quit_closure_.Run();
265 void WindowManager::OnConfigurationChanged() {
266 if (is_configuring_) {
267 should_configure_ = true;
268 return;
271 is_configuring_ = true;
272 delegate_->GrabServer();
273 delegate_->GetDisplays(
274 base::Bind(&WindowManager::OnDisplaysAquired, base::Unretained(this)));
277 void WindowManager::OnDisplaysAquired(
278 const std::vector<ui::DisplaySnapshot*>& displays) {
279 windows_.clear();
281 gfx::Point origin;
282 for (auto display : displays) {
283 if (!display->native_mode()) {
284 LOG(ERROR) << "Display " << display->display_id()
285 << " doesn't have a native mode";
286 continue;
289 delegate_->Configure(
290 *display, display->native_mode(), origin,
291 base::Bind(&WindowManager::OnDisplayConfigured, base::Unretained(this),
292 gfx::Rect(origin, display->native_mode()->size())));
293 origin.Offset(display->native_mode()->size().width(), 0);
295 delegate_->UngrabServer();
296 is_configuring_ = false;
298 if (should_configure_) {
299 should_configure_ = false;
300 base::ThreadTaskRunnerHandle::Get()->PostTask(
301 FROM_HERE, base::Bind(&WindowManager::OnConfigurationChanged,
302 base::Unretained(this)));
306 void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) {
307 if (success) {
308 scoped_ptr<DemoWindow> window(
309 new DemoWindow(this, &renderer_factory_, bounds));
310 window->Start();
311 windows_.push_back(window.Pass());
312 } else {
313 LOG(ERROR) << "Failed to configure display at " << bounds.ToString();
317 int main(int argc, char** argv) {
318 base::CommandLine::Init(argc, argv);
319 base::AtExitManager exit_manager;
321 // Initialize logging so we can enable VLOG messages.
322 logging::LoggingSettings settings;
323 logging::InitLogging(settings);
325 // Build UI thread message loop. This is used by platform
326 // implementations for event polling & running background tasks.
327 base::MessageLoopForUI message_loop;
329 ui::OzonePlatform::InitializeForUI();
330 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()
331 ->SetCurrentLayoutByName("us");
333 base::RunLoop run_loop;
335 WindowManager window_manager(run_loop.QuitClosure());
337 run_loop.Run();
339 return 0;