[go: nahoru, domu]

blob: 4b44c255e0e3fa63b25f3b06476e9c9da9d983b6 [file] [log] [blame]
spang@chromium.org85905ed2014-07-24 18:48:411// 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.
4
5#include "base/at_exit.h"
6#include "base/command_line.h"
dnicoara655c4e62015-02-11 18:25:567#include "base/memory/scoped_vector.h"
spang@chromium.org85905ed2014-07-24 18:48:418#include "base/message_loop/message_loop.h"
9#include "base/run_loop.h"
dnicoara655c4e62015-02-11 18:25:5610#include "base/thread_task_runner_handle.h"
spang@chromium.org85905ed2014-07-24 18:48:4111#include "base/timer/timer.h"
dnicoara655c4e62015-02-11 18:25:5612#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"
spangb7d90492015-01-12 16:07:5615#include "ui/events/event.h"
16#include "ui/events/keycodes/dom3/dom_code.h"
dnicoara6e408ee82015-01-14 03:55:2717#include "ui/events/ozone/layout/keyboard_layout_engine.h"
18#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
dnicoara3f6f5e052014-12-17 03:30:4519#include "ui/gfx/geometry/rect.h"
spang@chromium.org85905ed2014-07-24 18:48:4120#include "ui/gfx/geometry/size.h"
spang@chromium.org85905ed2014-07-24 18:48:4121#include "ui/gl/gl_surface.h"
dnicoara3f6f5e052014-12-17 03:30:4522#include "ui/ozone/demo/gl_renderer.h"
23#include "ui/ozone/demo/software_renderer.h"
dnicoara52f460f2014-12-17 17:18:1024#include "ui/ozone/demo/surfaceless_gl_renderer.h"
dnicoara655c4e62015-02-11 18:25:5625#include "ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h"
spang@chromium.org85905ed2014-07-24 18:48:4126#include "ui/ozone/public/ozone_platform.h"
dnicoara52f460f2014-12-17 17:18:1027#include "ui/ozone/public/ozone_switches.h"
spangaa2a3722014-09-03 05:14:5828#include "ui/ozone/public/ui_thread_gpu.h"
spang@chromium.org85905ed2014-07-24 18:48:4129#include "ui/platform_window/platform_window.h"
30#include "ui/platform_window/platform_window_delegate.h"
31
32const int kTestWindowWidth = 800;
33const int kTestWindowHeight = 600;
34
35const int kFrameDelayMilliseconds = 16;
36
spang@chromium.org85905ed2014-07-24 18:48:4137const char kDisableGpu[] = "disable-gpu";
dnicoara3f6f5e052014-12-17 03:30:4538
39const char kWindowSize[] = "window-size";
spang@chromium.org85905ed2014-07-24 18:48:4140
dnicoara655c4e62015-02-11 18:25:5641class DemoWindow;
42
43class 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
70class 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
spang@chromium.org85905ed2014-07-24 18:48:41106class DemoWindow : public ui::PlatformWindowDelegate {
107 public:
dnicoara655c4e62015-02-11 18:25:56108 DemoWindow(WindowManager* window_manager,
109 RendererFactory* renderer_factory,
110 const gfx::Rect& bounds)
111 : window_manager_(window_manager),
112 renderer_factory_(renderer_factory),
113 widget_(gfx::kNullAcceleratedWidget),
114 weak_ptr_factory_(this) {
115 platform_window_ =
116 ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds);
spang@chromium.org85905ed2014-07-24 18:48:41117 }
spanga3f37292014-11-07 23:19:01118 ~DemoWindow() override {}
spang@chromium.org85905ed2014-07-24 18:48:41119
120 gfx::AcceleratedWidget GetAcceleratedWidget() {
121 // TODO(spang): We should start rendering asynchronously.
spang@chromium.org5afd0bf2014-07-29 15:33:57122 DCHECK_NE(widget_, gfx::kNullAcceleratedWidget)
spang@chromium.org85905ed2014-07-24 18:48:41123 << "Widget not available synchronously";
124 return widget_;
125 }
126
127 gfx::Size GetSize() { return platform_window_->GetBounds().size(); }
128
dnicoara655c4e62015-02-11 18:25:56129 void Start() {
130 base::ThreadTaskRunnerHandle::Get()->PostTask(
131 FROM_HERE,
132 base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr()));
spang@chromium.org85905ed2014-07-24 18:48:41133 }
134
135 void Quit() {
136 StopAnimation();
dnicoara655c4e62015-02-11 18:25:56137 window_manager_->Quit();
138 }
spang@chromium.org85905ed2014-07-24 18:48:41139
140 // PlatformWindowDelegate:
dnicoara655c4e62015-02-11 18:25:56141 void OnBoundsChanged(const gfx::Rect& new_bounds) override {}
142 void OnDamageRect(const gfx::Rect& damaged_region) override {}
143 void DispatchEvent(ui::Event* event) override {
144 if (event->IsKeyEvent() &&
145 static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q)
146 Quit();
147 }
148 void OnCloseRequest() override { Quit(); }
149 void OnClosed() override {}
150 void OnWindowStateChanged(ui::PlatformWindowState new_state) override {}
151 void OnLostCapture() override {}
152 void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override {
spang@chromium.org5afd0bf2014-07-29 15:33:57153 DCHECK_NE(widget, gfx::kNullAcceleratedWidget);
spang@chromium.org85905ed2014-07-24 18:48:41154 widget_ = widget;
155 }
spanga3f37292014-11-07 23:19:01156 void OnActivationChanged(bool active) override {}
spang@chromium.org85905ed2014-07-24 18:48:41157
158 private:
dnicoara655c4e62015-02-11 18:25:56159 // 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 }
spang@chromium.org85905ed2014-07-24 18:48:41170
171 void StopAnimation() { timer_.Stop(); }
172
dnicoara655c4e62015-02-11 18:25:56173 WindowManager* window_manager_; // Not owned.
174 RendererFactory* renderer_factory_; // Not owned.
spangaa2a3722014-09-03 05:14:58175
dnicoara3f6f5e052014-12-17 03:30:45176 scoped_ptr<ui::Renderer> renderer_;
177
spang@chromium.org85905ed2014-07-24 18:48:41178 // Timer for animation.
dnicoara3f6f5e052014-12-17 03:30:45179 base::RepeatingTimer<ui::Renderer> timer_;
spang@chromium.org85905ed2014-07-24 18:48:41180
181 // Window-related state.
182 scoped_ptr<ui::PlatformWindow> platform_window_;
183 gfx::AcceleratedWidget widget_;
184
dnicoara655c4e62015-02-11 18:25:56185 base::WeakPtrFactory<DemoWindow> weak_ptr_factory_;
spangbb91b33b2015-01-09 23:06:17186
spang@chromium.org85905ed2014-07-24 18:48:41187 DISALLOW_COPY_AND_ASSIGN(DemoWindow);
188};
189
dnicoara655c4e62015-02-11 18:25:56190///////////////////////////////////////////////////////////////////////////////
191// RendererFactory implementation:
192
193RendererFactory::RendererFactory() : type_(SOFTWARE) {
194}
195
196RendererFactory::~RendererFactory() {
197}
198
199bool 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
215scoped_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
234WindowManager::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
262WindowManager::~WindowManager() {
263 if (delegate_)
264 delegate_->RemoveObserver(this);
265}
266
267void WindowManager::Quit() {
268 quit_closure_.Run();
269}
270
271void 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
283void 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
312void 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
spang@chromium.org85905ed2014-07-24 18:48:41323int main(int argc, char** argv) {
avi6b10fd02014-12-23 05:51:23324 base::CommandLine::Init(argc, argv);
spang@chromium.org85905ed2014-07-24 18:48:41325 base::AtExitManager exit_manager;
dnicoara655c4e62015-02-11 18:25:56326
327 // Initialize logging so we can enable VLOG messages.
328 logging::LoggingSettings settings;
329 logging::InitLogging(settings);
spang@chromium.org85905ed2014-07-24 18:48:41330
331 // Build UI thread message loop. This is used by platform
332 // implementations for event polling & running background tasks.
333 base::MessageLoopForUI message_loop;
334
335 ui::OzonePlatform::InitializeForUI();
dnicoara6e408ee82015-01-14 03:55:27336 ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine()
337 ->SetCurrentLayoutByName("us");
spang@chromium.org85905ed2014-07-24 18:48:41338
spang@chromium.org85905ed2014-07-24 18:48:41339 base::RunLoop run_loop;
spangbb91b33b2015-01-09 23:06:17340
dnicoara655c4e62015-02-11 18:25:56341 WindowManager window_manager(run_loop.QuitClosure());
spangbb91b33b2015-01-09 23:06:17342
343 run_loop.Run();
spang@chromium.org85905ed2014-07-24 18:48:41344
345 return 0;
346}