Index: ui/ozone/demo/ozone_demo.cc |
diff --git a/ui/ozone/demo/ozone_demo.cc b/ui/ozone/demo/ozone_demo.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..534b9141bc030777484610d6a9ab5ceb574d6206 |
--- /dev/null |
+++ b/ui/ozone/demo/ozone_demo.cc |
@@ -0,0 +1,346 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/at_exit.h" |
+#include "base/command_line.h" |
+#include "base/memory/scoped_vector.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "base/thread_task_runner_handle.h" |
+#include "ui/display/types/display_snapshot.h" |
+#include "ui/display/types/native_display_delegate.h" |
+#include "ui/display/types/native_display_observer.h" |
+#include "ui/events/event.h" |
+#include "ui/events/keycodes/dom/dom_code.h" |
+#include "ui/events/ozone/layout/keyboard_layout_engine.h" |
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" |
+#include "ui/gfx/geometry/rect.h" |
+#include "ui/gfx/geometry/size.h" |
+#include "ui/gl/gl_surface.h" |
+#include "ui/ozone/demo/gl_renderer.h" |
+#include "ui/ozone/demo/software_renderer.h" |
+#include "ui/ozone/demo/surfaceless_gl_renderer.h" |
+#include "ui/ozone/gpu/gpu_memory_buffer_factory_ozone_native_buffer.h" |
+#include "ui/ozone/public/ozone_gpu_test_helper.h" |
+#include "ui/ozone/public/ozone_platform.h" |
+#include "ui/ozone/public/ozone_switches.h" |
+#include "ui/platform_window/platform_window.h" |
+#include "ui/platform_window/platform_window_delegate.h" |
+ |
+const int kTestWindowWidth = 800; |
+const int kTestWindowHeight = 600; |
+ |
+const char kDisableGpu[] = "disable-gpu"; |
+ |
+const char kWindowSize[] = "window-size"; |
+ |
+class DemoWindow; |
+ |
+class RendererFactory { |
+ public: |
+ enum RendererType { |
+ GL, |
+ SURFACELESS_GL, |
+ SOFTWARE, |
+ }; |
+ |
+ RendererFactory(); |
+ ~RendererFactory(); |
+ |
+ bool Initialize(); |
+ scoped_ptr<ui::Renderer> CreateRenderer(gfx::AcceleratedWidget widget, |
+ const gfx::Size& size); |
+ |
+ private: |
+ RendererType type_ = SOFTWARE; |
+ |
+ // Helper for applications that do GL on main thread. |
+ ui::OzoneGpuTestHelper gpu_helper_; |
+ |
+ // Used by the surfaceless renderers to allocate buffers. |
+ ui::GpuMemoryBufferFactoryOzoneNativeBuffer buffer_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(RendererFactory); |
+}; |
+ |
+class WindowManager : public ui::NativeDisplayObserver { |
+ public: |
+ WindowManager(const base::Closure& quit_closure); |
+ ~WindowManager() override; |
+ |
+ void Quit(); |
+ |
+ void AddWindow(DemoWindow* window); |
+ void RemoveWindow(DemoWindow* window); |
+ |
+ private: |
+ void OnDisplaysAquired(const std::vector<ui::DisplaySnapshot*>& displays); |
+ void OnDisplayConfigured(const gfx::Rect& bounds, bool success); |
+ |
+ // ui::NativeDisplayDelegate: |
+ void OnConfigurationChanged() override; |
+ |
+ scoped_ptr<ui::NativeDisplayDelegate> delegate_; |
+ base::Closure quit_closure_; |
+ RendererFactory renderer_factory_; |
+ ScopedVector<DemoWindow> windows_; |
+ |
+ // Flags used to keep track of the current state of display configuration. |
+ // |
+ // True if configuring the displays. In this case a new display configuration |
+ // isn't started. |
+ bool is_configuring_ = false; |
+ |
+ // If |is_configuring_| is true and another display configuration event |
+ // happens, the event is deferred. This is set to true and a display |
+ // configuration will be scheduled after the current one finishes. |
+ bool should_configure_ = false; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(WindowManager); |
+}; |
+ |
+class DemoWindow : public ui::PlatformWindowDelegate { |
+ public: |
+ DemoWindow(WindowManager* window_manager, |
+ RendererFactory* renderer_factory, |
+ const gfx::Rect& bounds) |
+ : window_manager_(window_manager), |
+ renderer_factory_(renderer_factory), |
+ weak_ptr_factory_(this) { |
+ platform_window_ = |
+ ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds); |
+ } |
+ ~DemoWindow() override {} |
+ |
+ gfx::AcceleratedWidget GetAcceleratedWidget() { |
+ // TODO(spang): We should start rendering asynchronously. |
+ DCHECK_NE(widget_, gfx::kNullAcceleratedWidget) |
+ << "Widget not available synchronously"; |
+ return widget_; |
+ } |
+ |
+ gfx::Size GetSize() { return platform_window_->GetBounds().size(); } |
+ |
+ void Start() { |
+ LOG(INFO) << "DemoWindow::Start"; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr())); |
+ } |
+ |
+ void Quit() { |
+ window_manager_->Quit(); |
+ } |
+ |
+ // PlatformWindowDelegate: |
+ void OnBoundsChanged(const gfx::Rect& new_bounds) override {} |
+ void OnDamageRect(const gfx::Rect& damaged_region) override {} |
+ void DispatchEvent(ui::Event* event) override { |
+ if (event->IsKeyEvent() && |
+ static_cast<ui::KeyEvent*>(event)->code() == ui::DomCode::KEY_Q) |
+ Quit(); |
+ } |
+ void OnCloseRequest() override { Quit(); } |
+ void OnClosed() override {} |
+ void OnWindowStateChanged(ui::PlatformWindowState new_state) override {} |
+ void OnLostCapture() override {} |
+ void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override { |
+ LOG(INFO) << "OnAcceleratedWidgetAvailable " << widget; |
+ DCHECK_NE(widget, gfx::kNullAcceleratedWidget); |
+ widget_ = widget; |
+ } |
+ void OnActivationChanged(bool active) override {} |
+ |
+ private: |
+ // Since we pretend to have a GPU process, we should also pretend to |
+ // initialize the GPU resources via a posted task. |
+ void StartOnGpu() { |
+ LOG(INFO) << "StartOnGPU"; |
+ gfx::GLSurface::InitializeOneOff(); |
+ |
+ renderer_ = |
+ renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize()); |
+ renderer_->Initialize(); |
+ } |
+ |
+ WindowManager* window_manager_; // Not owned. |
+ RendererFactory* renderer_factory_; // Not owned. |
+ |
+ scoped_ptr<ui::Renderer> renderer_; |
+ |
+ // Window-related state. |
+ scoped_ptr<ui::PlatformWindow> platform_window_; |
+ gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget; |
+ |
+ base::WeakPtrFactory<DemoWindow> weak_ptr_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DemoWindow); |
+}; |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// RendererFactory implementation: |
+ |
+RendererFactory::RendererFactory() { |
+} |
+ |
+RendererFactory::~RendererFactory() { |
+} |
+ |
+bool RendererFactory::Initialize() { |
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
+ if (!command_line->HasSwitch(kDisableGpu) && |
+ gpu_helper_.Initialize(base::ThreadTaskRunnerHandle::Get(), |
+ base::ThreadTaskRunnerHandle::Get())) { |
+ if (command_line->HasSwitch(switches::kOzoneUseSurfaceless)) { |
+ type_ = SURFACELESS_GL; |
+ } else { |
+ type_ = GL; |
+ } |
+ } else { |
+ type_ = SOFTWARE; |
+ } |
+ |
+ return true; |
+} |
+ |
+scoped_ptr<ui::Renderer> RendererFactory::CreateRenderer( |
+ gfx::AcceleratedWidget widget, |
+ const gfx::Size& size) { |
+ switch (type_) { |
+ case GL: |
+ return make_scoped_ptr(new ui::GlRenderer(widget, size)); |
+ case SURFACELESS_GL: |
+ return make_scoped_ptr( |
+ new ui::SurfacelessGlRenderer(widget, size, &buffer_factory_)); |
+ case SOFTWARE: |
+ return make_scoped_ptr(new ui::SoftwareRenderer(widget, size)); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// WindowManager implementation: |
+ |
+WindowManager::WindowManager(const base::Closure& quit_closure) |
+ : delegate_( |
+ ui::OzonePlatform::GetInstance()->CreateNativeDisplayDelegate()), |
+ quit_closure_(quit_closure) { |
+ if (!renderer_factory_.Initialize()) |
+ LOG(FATAL) << "Failed to initialize renderer factory"; |
+ |
+ LOG(INFO) << "WindowManager() " << delegate_; |
+ |
+ if (delegate_) { |
+ delegate_->AddObserver(this); |
+ delegate_->Initialize(); |
+ OnConfigurationChanged(); |
+ } else { |
+ LOG(WARNING) << "No display delegate; falling back to test window"; |
+ int width = kTestWindowWidth; |
+ int height = kTestWindowHeight; |
+ sscanf(base::CommandLine::ForCurrentProcess() |
+ ->GetSwitchValueASCII(kWindowSize) |
+ .c_str(), |
+ "%dx%d", &width, &height); |
+ |
+ DemoWindow* window = new DemoWindow(this, &renderer_factory_, |
+ gfx::Rect(gfx::Size(width, height))); |
+ window->Start(); |
+ } |
+} |
+ |
+WindowManager::~WindowManager() { |
+ if (delegate_) |
+ delegate_->RemoveObserver(this); |
+} |
+ |
+void WindowManager::Quit() { |
+ quit_closure_.Run(); |
+} |
+ |
+void WindowManager::OnConfigurationChanged() { |
+ if (is_configuring_) { |
+ should_configure_ = true; |
+ return; |
+ } |
+ |
+ is_configuring_ = true; |
+ delegate_->GrabServer(); |
+ delegate_->GetDisplays( |
+ base::Bind(&WindowManager::OnDisplaysAquired, base::Unretained(this))); |
+} |
+ |
+void WindowManager::OnDisplaysAquired( |
+ const std::vector<ui::DisplaySnapshot*>& displays) { |
+ windows_.clear(); |
+ |
+ gfx::Point origin; |
+ for (auto display : displays) { |
+ if (!display->native_mode()) { |
+ LOG(ERROR) << "Display " << display->display_id() |
+ << " doesn't have a native mode"; |
+ continue; |
+ } |
+ |
+ delegate_->Configure( |
+ *display, display->native_mode(), origin, |
+ base::Bind(&WindowManager::OnDisplayConfigured, base::Unretained(this), |
+ gfx::Rect(origin, display->native_mode()->size()))); |
+ origin.Offset(display->native_mode()->size().width(), 0); |
+ } |
+ delegate_->UngrabServer(); |
+ is_configuring_ = false; |
+ |
+ if (should_configure_) { |
+ should_configure_ = false; |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, base::Bind(&WindowManager::OnConfigurationChanged, |
+ base::Unretained(this))); |
+ } |
+} |
+ |
+void WindowManager::OnDisplayConfigured(const gfx::Rect& bounds, bool success) { |
+ LOG(INFO) << "OnDisplayConfigured " << success; |
+ if (success) { |
+ scoped_ptr<DemoWindow> window( |
+ new DemoWindow(this, &renderer_factory_, bounds)); |
+ window->Start(); |
+ windows_.push_back(window.Pass()); |
+ } else { |
+ LOG(ERROR) << "Failed to configure display at " << bounds.ToString(); |
+ } |
+} |
+ |
+int main(int argc, char** argv) { |
+ base::CommandLine::Init(argc, argv); |
+ base::AtExitManager exit_manager; |
+ |
+ // Initialize logging so we can enable VLOG messages. |
+ logging::LoggingSettings settings; |
+ logging::InitLogging(settings); |
+ |
+ // Build UI thread message loop. This is used by platform |
+ // implementations for event polling & running background tasks. |
+ base::MessageLoopForUI message_loop; |
+ |
+ ui::OzonePlatform::InitializeForUI(); |
+ LOG(INFO) << "InitializeForUI complete"; |
+ |
+ ui::OzonePlatform::InitializeForGPU(); |
+ LOG(INFO) << "InitializeForGPU complete"; |
+ |
+ ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() |
+ ->SetCurrentLayoutByName("us"); |
+ |
+ base::RunLoop run_loop; |
+ |
+ WindowManager window_manager(run_loop.QuitClosure()); |
+ |
+ LOG(INFO) << "demo entering run loop"; |
+ run_loop.Run(); |
+ LOG(INFO) << "demo returning from run loop"; |
+ |
+ return 0; |
+} |