Index: ui/ozone/demo/ozone_demo.cc |
diff --git a/ui/ozone/demo/ozone_demo.cc b/ui/ozone/demo/ozone_demo.cc |
index 32d7fde700b5e46cc1fd03965ce0f80f0cd0e837..4b44c255e0e3fa63b25f3b06476e9c9da9d983b6 100644 |
--- a/ui/ozone/demo/ozone_demo.cc |
+++ b/ui/ozone/demo/ozone_demo.cc |
@@ -4,9 +4,14 @@ |
#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 "base/timer/timer.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/dom3/dom_code.h" |
#include "ui/events/ozone/layout/keyboard_layout_engine.h" |
@@ -17,6 +22,7 @@ |
#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_platform.h" |
#include "ui/ozone/public/ozone_switches.h" |
#include "ui/ozone/public/ui_thread_gpu.h" |
@@ -32,18 +38,82 @@ const char kDisableGpu[] = "disable-gpu"; |
const char kWindowSize[] = "window-size"; |
-class DemoWindow : public ui::PlatformWindowDelegate { |
+class DemoWindow; |
+ |
+class RendererFactory { |
public: |
- DemoWindow() : widget_(gfx::kNullAcceleratedWidget) { |
- int width = kTestWindowWidth; |
- int height = kTestWindowHeight; |
- sscanf(base::CommandLine::ForCurrentProcess() |
- ->GetSwitchValueASCII(kWindowSize) |
- .c_str(), |
- "%dx%d", &width, &height); |
+ 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_; |
+ |
+ // Helper for applications that do GL on main thread. |
+ ui::UiThreadGpu ui_thread_gpu_; |
+ |
+ // 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_; |
- platform_window_ = ui::OzonePlatform::GetInstance()->CreatePlatformWindow( |
- this, gfx::Rect(width, height)); |
+ // 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_; |
+ |
+ 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), |
+ widget_(gfx::kNullAcceleratedWidget), |
+ weak_ptr_factory_(this) { |
+ platform_window_ = |
+ ui::OzonePlatform::GetInstance()->CreatePlatformWindow(this, bounds); |
} |
~DemoWindow() override {} |
@@ -56,61 +126,52 @@ class DemoWindow : public ui::PlatformWindowDelegate { |
gfx::Size GetSize() { return platform_window_->GetBounds().size(); } |
- void Start(const base::Closure& quit_closure) { |
- quit_closure_ = quit_closure; |
- |
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kDisableGpu) && |
- gfx::GLSurface::InitializeOneOff() && StartInProcessGpu()) { |
- if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kOzoneUseSurfaceless)) { |
- renderer_.reset( |
- new ui::SurfacelessGlRenderer(GetAcceleratedWidget(), GetSize())); |
- } else { |
- renderer_.reset(new ui::GlRenderer(GetAcceleratedWidget(), GetSize())); |
- } |
- } else { |
- renderer_.reset( |
- new ui::SoftwareRenderer(GetAcceleratedWidget(), GetSize())); |
- } |
- |
- if (renderer_->Initialize()) { |
- timer_.Start(FROM_HERE, |
- base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds), |
- renderer_.get(), &ui::Renderer::RenderFrame); |
- } else { |
- LOG(ERROR) << "Failed to create drawing surface"; |
- Quit(); |
- } |
+ void Start() { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr())); |
} |
void Quit() { |
StopAnimation(); |
- quit_closure_.Run(); |
- } |
+ 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 { |
+ 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 { |
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() { |
+ renderer_ = |
+ renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize()); |
+ if (renderer_->Initialize()) { |
+ timer_.Start(FROM_HERE, |
+ base::TimeDelta::FromMilliseconds(kFrameDelayMilliseconds), |
+ renderer_.get(), &ui::Renderer::RenderFrame); |
+ } |
+ } |
void StopAnimation() { timer_.Stop(); } |
- bool StartInProcessGpu() { return ui_thread_gpu_.Initialize(); } |
+ WindowManager* window_manager_; // Not owned. |
+ RendererFactory* renderer_factory_; // Not owned. |
scoped_ptr<ui::Renderer> renderer_; |
@@ -121,18 +182,152 @@ class DemoWindow : public ui::PlatformWindowDelegate { |
scoped_ptr<ui::PlatformWindow> platform_window_; |
gfx::AcceleratedWidget widget_; |
- // Helper for applications that do GL on main thread. |
- ui::UiThreadGpu ui_thread_gpu_; |
- |
- base::Closure quit_closure_; |
+ base::WeakPtrFactory<DemoWindow> weak_ptr_factory_; |
DISALLOW_COPY_AND_ASSIGN(DemoWindow); |
}; |
+/////////////////////////////////////////////////////////////////////////////// |
+// RendererFactory implementation: |
+ |
+RendererFactory::RendererFactory() : type_(SOFTWARE) { |
+} |
+ |
+RendererFactory::~RendererFactory() { |
+} |
+ |
+bool RendererFactory::Initialize() { |
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
+ if (!command_line->HasSwitch(kDisableGpu) && |
+ gfx::GLSurface::InitializeOneOff() && ui_thread_gpu_.Initialize()) { |
+ 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 scoped_ptr<ui::Renderer>(new ui::GlRenderer(widget, size)); |
+ case SURFACELESS_GL: |
+ return scoped_ptr<ui::Renderer>( |
+ new ui::SurfacelessGlRenderer(widget, size, &buffer_factory_)); |
+ case SOFTWARE: |
+ return scoped_ptr<ui::Renderer>(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), |
+ is_configuring_(false), |
+ should_configure_(false) { |
+ if (!renderer_factory_.Initialize()) |
+ LOG(FATAL) << "Failed to initialize renderer factory"; |
+ |
+ 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) { |
+ if (success) { |
+ scoped_ptr<DemoWindow> window( |
+ new DemoWindow(this, &renderer_factory_, bounds)); |
+ window->Start(); |
+ windows_.push_back(window.release()); |
+ } 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; |
@@ -143,8 +338,7 @@ int main(int argc, char** argv) { |
base::RunLoop run_loop; |
- scoped_ptr<DemoWindow> window(new DemoWindow); |
- window->Start(run_loop.QuitClosure()); |
+ WindowManager window_manager(run_loop.QuitClosure()); |
run_loop.Run(); |