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";
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
);
46 surface
= gfx::GLSurface::CreateViewGLSurface(widget
);
50 class RendererFactory
{
61 scoped_ptr
<ui::Renderer
> CreateRenderer(gfx::AcceleratedWidget widget
,
62 const gfx::Size
& size
);
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
{
75 WindowManager(const base::Closure
& quit_closure
);
76 ~WindowManager() override
;
80 void AddWindow(DemoWindow
* window
);
81 void RemoveWindow(DemoWindow
* window
);
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
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
{
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) {
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";
129 gfx::Size
GetSize() { return platform_window_
->GetBounds().size(); }
132 base::ThreadTaskRunnerHandle::Get()->PostTask(
134 base::Bind(&DemoWindow::StartOnGpu
, weak_ptr_factory_
.GetWeakPtr()));
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
)
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
);
158 void OnActivationChanged(bool active
) override
{}
161 // Since we pretend to have a GPU process, we should also pretend to
162 // initialize the GPU resources via a posted task.
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())) {
206 scoped_ptr
<ui::Renderer
> RendererFactory::CreateRenderer(
207 gfx::AcceleratedWidget widget
,
208 const gfx::Size
& size
) {
211 scoped_refptr
<gfx::GLSurface
> surface
= CreateGLSurface(widget
);
213 LOG(FATAL
) << "Failed to create GL surface";
214 if (surface
->IsSurfaceless())
215 return make_scoped_ptr(
216 new ui::SurfacelessGlRenderer(widget
, surface
, size
));
218 return make_scoped_ptr(new ui::GlRenderer(widget
, surface
, size
));
221 return make_scoped_ptr(new ui::SoftwareRenderer(widget
, size
));
227 ///////////////////////////////////////////////////////////////////////////////
228 // WindowManager implementation:
230 WindowManager::WindowManager(const base::Closure
& quit_closure
)
232 ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()),
233 quit_closure_(quit_closure
) {
234 if (!renderer_factory_
.Initialize())
235 LOG(FATAL
) << "Failed to initialize renderer factory";
238 delegate_
->AddObserver(this);
239 delegate_
->Initialize();
240 OnConfigurationChanged();
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
)
248 "%dx%d", &width
, &height
);
250 DemoWindow
* window
= new DemoWindow(this, &renderer_factory_
,
251 gfx::Rect(gfx::Size(width
, height
)));
256 WindowManager::~WindowManager() {
258 delegate_
->RemoveObserver(this);
261 void WindowManager::Quit() {
265 void WindowManager::OnConfigurationChanged() {
266 if (is_configuring_
) {
267 should_configure_
= true;
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
) {
282 for (auto display
: displays
) {
283 if (!display
->native_mode()) {
284 LOG(ERROR
) << "Display " << display
->display_id()
285 << " doesn't have a native mode";
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
) {
308 scoped_ptr
<DemoWindow
> window(
309 new DemoWindow(this, &renderer_factory_
, bounds
));
311 windows_
.push_back(window
.Pass());
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());