Commit 7ca92c28 authored by kylechar's avatar kylechar Committed by Commit Bot

ozone: Headless with osmesa GL outputs to file.

Add a custom GLSurfaceOSMesaPng that outputs to file. Unfortunately the
GPU sandbox will block this from writing to file, so it only works
without the GPU sandbox.

Bug: 783792
Change-Id: I868702aa5dab81bffb8ea4867d659225255e5d50
Reviewed-on: https://chromium-review.googlesource.com/758608
Commit-Queue: kylechar <kylechar@chromium.org>
Reviewed-by: default avatarRobert Kroeger <rjkroege@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#516061}
parent b317a798
...@@ -152,6 +152,7 @@ static const char* const kSwitchNames[] = { ...@@ -152,6 +152,7 @@ static const char* const kSwitchNames[] = {
#endif #endif
#if defined(USE_OZONE) #if defined(USE_OZONE)
switches::kOzonePlatform, switches::kOzonePlatform,
switches::kOzoneDumpFile,
#endif #endif
#if defined(USE_X11) #if defined(USE_X11)
switches::kX11Display, switches::kX11Display,
......
...@@ -33,5 +33,9 @@ source_set("common") { ...@@ -33,5 +33,9 @@ source_set("common") {
"//ui/gl:gl_features", "//ui/gl:gl_features",
] ]
data_deps = [
"//third_party/mesa:osmesa",
]
visibility = [ "//ui/ozone/platform/*" ] visibility = [ "//ui/ozone/platform/*" ]
} }
...@@ -8,6 +8,8 @@ source_set("headless") { ...@@ -8,6 +8,8 @@ source_set("headless") {
sources = [ sources = [
"client_native_pixmap_factory_headless.cc", "client_native_pixmap_factory_headless.cc",
"client_native_pixmap_factory_headless.h", "client_native_pixmap_factory_headless.h",
"gl_surface_osmesa_png.cc",
"gl_surface_osmesa_png.h",
"headless_surface_factory.cc", "headless_surface_factory.cc",
"headless_surface_factory.h", "headless_surface_factory.h",
"headless_window.cc", "headless_window.cc",
......
// Copyright 2017 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 "ui/ozone/platform/headless/gl_surface_osmesa_png.h"
#include <vector>
#include "base/files/file_util.h"
#include "base/task_scheduler/post_task.h"
#include "ui/gfx/codec/png_codec.h"
namespace ui {
namespace {
constexpr int kBytesPerPixelBGRA = 4;
void WritePngToFile(const base::FilePath& path,
std::vector<unsigned char> png_data) {
DCHECK(!path.empty());
base::WriteFile(path, reinterpret_cast<const char*>(png_data.data()),
png_data.size());
}
} // namespace
GLSurfaceOSMesaPng::GLSurfaceOSMesaPng(base::FilePath output_path)
: GLSurfaceOSMesa(
gl::GLSurfaceFormat(gl::GLSurfaceFormat::PIXEL_LAYOUT_BGRA),
gfx::Size(1, 1)),
output_path_(output_path) {}
bool GLSurfaceOSMesaPng::IsOffscreen() {
return false;
}
gfx::SwapResult GLSurfaceOSMesaPng::SwapBuffers() {
if (!output_path_.empty())
WriteBufferToPng();
return gfx::SwapResult::SWAP_ACK;
}
GLSurfaceOSMesaPng::~GLSurfaceOSMesaPng() {
Destroy();
}
void GLSurfaceOSMesaPng::WriteBufferToPng() {
// TODO(crbug.com/783792): Writing the PNG to a file won't work with the GPU
// sandbox. This will produce no output unless --no-sandbox is used. Make this
// work with a file handle passed from browser process and possibly change
// output to be video.
gfx::Size size = GetSize();
std::vector<unsigned char> png_data;
if (gfx::PNGCodec::Encode(static_cast<unsigned char*>(GetHandle()),
gfx::PNGCodec::FORMAT_BGRA, size,
size.width() * kBytesPerPixelBGRA,
false /* discard_transparency */,
std::vector<gfx::PNGCodec::Comment>(), &png_data)) {
base::PostTaskWithTraits(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::Bind(&WritePngToFile, output_path_, base::Passed(&png_data)));
}
}
} // namespace ui
// Copyright 2017 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.
#ifndef UI_OZONE_PLATFORM_HEADLESS_GL_SURFACE_OSMESA_PNG_H_
#define UI_OZONE_PLATFORM_HEADLESS_GL_SURFACE_OSMESA_PNG_H_
#include "base/files/file_path.h"
#include "base/macros.h"
#include "ui/gl/gl_surface_osmesa.h"
namespace ui {
class GLSurfaceOSMesaPng : public gl::GLSurfaceOSMesa {
public:
explicit GLSurfaceOSMesaPng(base::FilePath output_path);
// gl::GLSurfaceOSMesa:
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
private:
~GLSurfaceOSMesaPng() override;
// Write contents of buffer out to PNG file at |output_path_|.
void WriteBufferToPng();
// If not empty then buffer contents will be written out to this location on
// swap.
base::FilePath output_path_;
DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesaPng);
};
} // namespace ui
#endif // UI_OZONE_PLATFORM_HEADLESS_GL_SURFACE_OSMESA_PNG_H_
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/location.h" #include "base/location.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h" #include "base/task_scheduler/post_task.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
...@@ -18,6 +19,7 @@ ...@@ -18,6 +19,7 @@
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/gfx/vsync_provider.h" #include "ui/gfx/vsync_provider.h"
#include "ui/ozone/common/gl_ozone_osmesa.h" #include "ui/ozone/common/gl_ozone_osmesa.h"
#include "ui/ozone/platform/headless/gl_surface_osmesa_png.h"
#include "ui/ozone/platform/headless/headless_window.h" #include "ui/ozone/platform/headless/headless_window.h"
#include "ui/ozone/platform/headless/headless_window_manager.h" #include "ui/ozone/platform/headless/headless_window_manager.h"
#include "ui/ozone/public/surface_ozone_canvas.h" #include "ui/ozone/public/surface_ozone_canvas.h"
...@@ -37,7 +39,7 @@ void WriteDataToFile(const base::FilePath& location, const SkBitmap& bitmap) { ...@@ -37,7 +39,7 @@ void WriteDataToFile(const base::FilePath& location, const SkBitmap& bitmap) {
// TODO(altimin): Find a proper way to capture rendering output. // TODO(altimin): Find a proper way to capture rendering output.
class FileSurface : public SurfaceOzoneCanvas { class FileSurface : public SurfaceOzoneCanvas {
public: public:
explicit FileSurface(const base::FilePath& location) : location_(location) {} explicit FileSurface(const base::FilePath& location) : base_path_(location) {}
~FileSurface() override {} ~FileSurface() override {}
// SurfaceOzoneCanvas overrides: // SurfaceOzoneCanvas overrides:
...@@ -47,7 +49,7 @@ class FileSurface : public SurfaceOzoneCanvas { ...@@ -47,7 +49,7 @@ class FileSurface : public SurfaceOzoneCanvas {
} }
sk_sp<SkSurface> GetSurface() override { return surface_; } sk_sp<SkSurface> GetSurface() override { return surface_; }
void PresentCanvas(const gfx::Rect& damage) override { void PresentCanvas(const gfx::Rect& damage) override {
if (location_.empty()) if (base_path_.empty())
return; return;
SkBitmap bitmap; SkBitmap bitmap;
bitmap.allocPixels(surface_->getCanvas()->imageInfo()); bitmap.allocPixels(surface_->getCanvas()->imageInfo());
...@@ -58,7 +60,7 @@ class FileSurface : public SurfaceOzoneCanvas { ...@@ -58,7 +60,7 @@ class FileSurface : public SurfaceOzoneCanvas {
base::PostTaskWithTraits( base::PostTaskWithTraits(
FROM_HERE, FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::Bind(&WriteDataToFile, location_, bitmap)); base::Bind(&WriteDataToFile, base_path_, bitmap));
} }
} }
std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override { std::unique_ptr<gfx::VSyncProvider> CreateVSyncProvider() override {
...@@ -66,7 +68,7 @@ class FileSurface : public SurfaceOzoneCanvas { ...@@ -66,7 +68,7 @@ class FileSurface : public SurfaceOzoneCanvas {
} }
private: private:
base::FilePath location_; base::FilePath base_path_;
sk_sp<SkSurface> surface_; sk_sp<SkSurface> surface_;
}; };
...@@ -103,20 +105,46 @@ class TestPixmap : public gfx::NativePixmap { ...@@ -103,20 +105,46 @@ class TestPixmap : public gfx::NativePixmap {
DISALLOW_COPY_AND_ASSIGN(TestPixmap); DISALLOW_COPY_AND_ASSIGN(TestPixmap);
}; };
} // namespace class GLOzoneOSMesaHeadless : public GLOzoneOSMesa {
public:
explicit GLOzoneOSMesaHeadless(HeadlessSurfaceFactory* surface_factory)
: surface_factory_(surface_factory) {}
~GLOzoneOSMesaHeadless() override = default;
// GLOzone:
scoped_refptr<gl::GLSurface> CreateViewGLSurface(
gfx::AcceleratedWidget window) override {
return gl::InitializeGLSurface(
new GLSurfaceOSMesaPng(surface_factory_->GetPathForWidget(window)));
}
private:
HeadlessSurfaceFactory* const surface_factory_;
DISALLOW_COPY_AND_ASSIGN(GLOzoneOSMesaHeadless);
};
HeadlessSurfaceFactory::HeadlessSurfaceFactory() } // namespace
: HeadlessSurfaceFactory(nullptr) {}
HeadlessSurfaceFactory::HeadlessSurfaceFactory( HeadlessSurfaceFactory::HeadlessSurfaceFactory(base::FilePath base_path)
HeadlessWindowManager* window_manager) : base_path_(base_path) {
: window_manager_(window_manager) { CheckBasePath();
#if !defined(OS_FUCHSIA) #if !defined(OS_FUCHSIA)
osmesa_implementation_ = std::make_unique<GLOzoneOSMesa>(); osmesa_implementation_ = std::make_unique<GLOzoneOSMesaHeadless>(this);
#endif #endif
} }
HeadlessSurfaceFactory::~HeadlessSurfaceFactory() {} HeadlessSurfaceFactory::~HeadlessSurfaceFactory() = default;
base::FilePath HeadlessSurfaceFactory::GetPathForWidget(
gfx::AcceleratedWidget widget) {
if (base_path_.empty() || base_path_ == base::FilePath("/dev/null"))
return base_path_;
// Disambiguate multiple window output files with the window id.
return base_path_.Append(base::IntToString(widget) + ".png");
}
std::vector<gl::GLImplementation> std::vector<gl::GLImplementation>
HeadlessSurfaceFactory::GetAllowedGLImplementations() { HeadlessSurfaceFactory::GetAllowedGLImplementations() {
...@@ -139,8 +167,7 @@ GLOzone* HeadlessSurfaceFactory::GetGLOzone( ...@@ -139,8 +167,7 @@ GLOzone* HeadlessSurfaceFactory::GetGLOzone(
std::unique_ptr<SurfaceOzoneCanvas> std::unique_ptr<SurfaceOzoneCanvas>
HeadlessSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) { HeadlessSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) {
HeadlessWindow* window = window_manager_->GetWindow(widget); return std::make_unique<FileSurface>(GetPathForWidget(widget));
return base::WrapUnique<SurfaceOzoneCanvas>(new FileSurface(window->path()));
} }
scoped_refptr<gfx::NativePixmap> HeadlessSurfaceFactory::CreateNativePixmap( scoped_refptr<gfx::NativePixmap> HeadlessSurfaceFactory::CreateNativePixmap(
...@@ -151,4 +178,16 @@ scoped_refptr<gfx::NativePixmap> HeadlessSurfaceFactory::CreateNativePixmap( ...@@ -151,4 +178,16 @@ scoped_refptr<gfx::NativePixmap> HeadlessSurfaceFactory::CreateNativePixmap(
return new TestPixmap(format); return new TestPixmap(format);
} }
void HeadlessSurfaceFactory::CheckBasePath() const {
if (base_path_.empty())
return;
if (!DirectoryExists(base_path_) && !base::CreateDirectory(base_path_) &&
base_path_ != base::FilePath("/dev/null"))
PLOG(FATAL) << "Unable to create output directory";
if (!base::PathIsWritable(base_path_))
PLOG(FATAL) << "Unable to write to output location";
}
} // namespace ui } // namespace ui
...@@ -8,20 +8,20 @@ ...@@ -8,20 +8,20 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/ozone/public/gl_ozone.h" #include "ui/ozone/public/gl_ozone.h"
#include "ui/ozone/public/surface_factory_ozone.h" #include "ui/ozone/public/surface_factory_ozone.h"
namespace ui { namespace ui {
class HeadlessWindowManager;
class HeadlessSurfaceFactory : public SurfaceFactoryOzone { class HeadlessSurfaceFactory : public SurfaceFactoryOzone {
public: public:
HeadlessSurfaceFactory(); explicit HeadlessSurfaceFactory(base::FilePath base_path);
explicit HeadlessSurfaceFactory(HeadlessWindowManager* window_manager);
~HeadlessSurfaceFactory() override; ~HeadlessSurfaceFactory() override;
base::FilePath GetPathForWidget(gfx::AcceleratedWidget widget);
// SurfaceFactoryOzone: // SurfaceFactoryOzone:
std::vector<gl::GLImplementation> GetAllowedGLImplementations() override; std::vector<gl::GLImplementation> GetAllowedGLImplementations() override;
GLOzone* GetGLOzone(gl::GLImplementation implementation) override; GLOzone* GetGLOzone(gl::GLImplementation implementation) override;
...@@ -34,7 +34,10 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone { ...@@ -34,7 +34,10 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone {
gfx::BufferUsage usage) override; gfx::BufferUsage usage) override;
private: private:
HeadlessWindowManager* window_manager_; void CheckBasePath() const;
// Base path for window output PNGs.
base::FilePath base_path_;
std::unique_ptr<GLOzone> osmesa_implementation_; std::unique_ptr<GLOzone> osmesa_implementation_;
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include <string> #include <string>
#include "base/files/file_path.h"
#include "base/strings/string_number_conversions.h"
#include "ui/events/platform/platform_event_source.h" #include "ui/events/platform/platform_event_source.h"
#include "ui/ozone/platform/headless/headless_window_manager.h" #include "ui/ozone/platform/headless/headless_window_manager.h"
#include "ui/platform_window/platform_window_delegate.h" #include "ui/platform_window/platform_window_delegate.h"
...@@ -26,15 +24,6 @@ HeadlessWindow::~HeadlessWindow() { ...@@ -26,15 +24,6 @@ HeadlessWindow::~HeadlessWindow() {
manager_->RemoveWindow(widget_, this); manager_->RemoveWindow(widget_, this);
} }
base::FilePath HeadlessWindow::path() {
base::FilePath base_path = manager_->base_path();
if (base_path.empty() || base_path == base::FilePath("/dev/null"))
return base_path;
// Disambiguate multiple window output files with the window id.
return base_path.Append(base::IntToString(widget_));
}
gfx::Rect HeadlessWindow::GetBounds() { gfx::Rect HeadlessWindow::GetBounds() {
return bounds_; return bounds_;
} }
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#ifndef UI_OZONE_PLATFORM_HEADLESS_HEADLESS_WINDOW_H_ #ifndef UI_OZONE_PLATFORM_HEADLESS_HEADLESS_WINDOW_H_
#define UI_OZONE_PLATFORM_HEADLESS_HEADLESS_WINDOW_H_ #define UI_OZONE_PLATFORM_HEADLESS_HEADLESS_WINDOW_H_
#include "base/files/file_path.h"
#include "base/macros.h" #include "base/macros.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
...@@ -23,9 +22,6 @@ class HeadlessWindow : public PlatformWindow { ...@@ -23,9 +22,6 @@ class HeadlessWindow : public PlatformWindow {
const gfx::Rect& bounds); const gfx::Rect& bounds);
~HeadlessWindow() override; ~HeadlessWindow() override;
// Path for image file for this window.
base::FilePath path();
// PlatformWindow: // PlatformWindow:
gfx::Rect GetBounds() override; gfx::Rect GetBounds() override;
void SetBounds(const gfx::Rect& bounds) override; void SetBounds(const gfx::Rect& bounds) override;
......
...@@ -4,29 +4,14 @@ ...@@ -4,29 +4,14 @@
#include "ui/ozone/platform/headless/headless_window_manager.h" #include "ui/ozone/platform/headless/headless_window_manager.h"
#include "base/files/file_util.h"
#include "base/location.h"
namespace ui { namespace ui {
HeadlessWindowManager::HeadlessWindowManager( HeadlessWindowManager::HeadlessWindowManager() = default;
const base::FilePath& dump_location)
: location_(dump_location) {}
HeadlessWindowManager::~HeadlessWindowManager() { HeadlessWindowManager::~HeadlessWindowManager() {
DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(thread_checker_.CalledOnValidThread());
} }
void HeadlessWindowManager::Initialize() {
if (location_.empty())
return;
if (!DirectoryExists(location_) && !base::CreateDirectory(location_) &&
location_ != base::FilePath("/dev/null"))
PLOG(FATAL) << "unable to create output directory";
if (!base::PathIsWritable(location_))
PLOG(FATAL) << "unable to write to output location";
}
int32_t HeadlessWindowManager::AddWindow(HeadlessWindow* window) { int32_t HeadlessWindowManager::AddWindow(HeadlessWindow* window) {
return windows_.Add(window); return windows_.Add(window);
} }
...@@ -41,8 +26,4 @@ HeadlessWindow* HeadlessWindowManager::GetWindow(int32_t window_id) { ...@@ -41,8 +26,4 @@ HeadlessWindow* HeadlessWindowManager::GetWindow(int32_t window_id) {
return windows_.Lookup(window_id); return windows_.Lookup(window_id);
} }
base::FilePath HeadlessWindowManager::base_path() const {
return location_;
}
} // namespace ui } // namespace ui
...@@ -22,12 +22,9 @@ class HeadlessWindow; ...@@ -22,12 +22,9 @@ class HeadlessWindow;
class HeadlessWindowManager { class HeadlessWindowManager {
public: public:
explicit HeadlessWindowManager(const base::FilePath& dump_location); HeadlessWindowManager();
~HeadlessWindowManager(); ~HeadlessWindowManager();
// Initialize (mainly check that we have a place to write output to).
void Initialize();
// Register a new window. Returns the window id. // Register a new window. Returns the window id.
int32_t AddWindow(HeadlessWindow* window); int32_t AddWindow(HeadlessWindow* window);
...@@ -37,12 +34,7 @@ class HeadlessWindowManager { ...@@ -37,12 +34,7 @@ class HeadlessWindowManager {
// Find a window object by id; // Find a window object by id;
HeadlessWindow* GetWindow(int32_t window_id); HeadlessWindow* GetWindow(int32_t window_id);
// User-supplied path for images.
base::FilePath base_path() const;
private: private:
base::FilePath location_;
base::IDMap<HeadlessWindow*> windows_; base::IDMap<HeadlessWindow*> windows_;
base::ThreadChecker thread_checker_; base::ThreadChecker thread_checker_;
......
...@@ -33,8 +33,8 @@ namespace { ...@@ -33,8 +33,8 @@ namespace {
// sure that the PlatformEventSource has an instance while in unit tests. // sure that the PlatformEventSource has an instance while in unit tests.
class HeadlessPlatformEventSource : public ui::PlatformEventSource { class HeadlessPlatformEventSource : public ui::PlatformEventSource {
public: public:
HeadlessPlatformEventSource() {} HeadlessPlatformEventSource() = default;
~HeadlessPlatformEventSource() override {} ~HeadlessPlatformEventSource() override = default;
private: private:
DISALLOW_COPY_AND_ASSIGN(HeadlessPlatformEventSource); DISALLOW_COPY_AND_ASSIGN(HeadlessPlatformEventSource);
...@@ -43,9 +43,9 @@ class HeadlessPlatformEventSource : public ui::PlatformEventSource { ...@@ -43,9 +43,9 @@ class HeadlessPlatformEventSource : public ui::PlatformEventSource {
// OzonePlatform for headless mode // OzonePlatform for headless mode
class OzonePlatformHeadless : public OzonePlatform { class OzonePlatformHeadless : public OzonePlatform {
public: public:
OzonePlatformHeadless(const base::FilePath& dump_file) explicit OzonePlatformHeadless(const base::FilePath& dump_file)
: file_path_(dump_file) {} : file_path_(dump_file) {}
~OzonePlatformHeadless() override {} ~OzonePlatformHeadless() override = default;
// OzonePlatform: // OzonePlatform:
ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override { ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
...@@ -69,8 +69,8 @@ class OzonePlatformHeadless : public OzonePlatform { ...@@ -69,8 +69,8 @@ class OzonePlatformHeadless : public OzonePlatform {
std::unique_ptr<PlatformWindow> CreatePlatformWindow( std::unique_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate, PlatformWindowDelegate* delegate,
const gfx::Rect& bounds) override { const gfx::Rect& bounds) override {
return base::WrapUnique<PlatformWindow>( return std::make_unique<HeadlessWindow>(delegate, window_manager_.get(),
new HeadlessWindow(delegate, window_manager_.get(), bounds)); bounds);
} }
std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate() std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
override { override {
...@@ -78,24 +78,23 @@ class OzonePlatformHeadless : public OzonePlatform { ...@@ -78,24 +78,23 @@ class OzonePlatformHeadless : public OzonePlatform {
} }
void InitializeUI(const InitParams& params) override { void InitializeUI(const InitParams& params) override {
window_manager_.reset(new HeadlessWindowManager(file_path_)); window_manager_ = std::make_unique<HeadlessWindowManager>();
window_manager_->Initialize(); surface_factory_ = std::make_unique<HeadlessSurfaceFactory>(file_path_);
surface_factory_.reset(new HeadlessSurfaceFactory(window_manager_.get()));
// This unbreaks tests that create their own. // This unbreaks tests that create their own.
if (!PlatformEventSource::GetInstance()) if (!PlatformEventSource::GetInstance())
platform_event_source_.reset(new HeadlessPlatformEventSource); platform_event_source_ = std::make_unique<HeadlessPlatformEventSource>();
KeyboardLayoutEngineManager::SetKeyboardLayoutEngine( KeyboardLayoutEngineManager::SetKeyboardLayoutEngine(
std::make_unique<StubKeyboardLayoutEngine>()); std::make_unique<StubKeyboardLayoutEngine>());
overlay_manager_.reset(new StubOverlayManager()); overlay_manager_ = std::make_unique<StubOverlayManager>();
input_controller_ = CreateStubInputController(); input_controller_ = CreateStubInputController();
cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone); cursor_factory_ozone_ = std::make_unique<BitmapCursorFactoryOzone>();
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost()); gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
} }
void InitializeGPU(const InitParams& params) override { void InitializeGPU(const InitParams& params) override {
if (!surface_factory_) if (!surface_factory_)
surface_factory_.reset(new HeadlessSurfaceFactory()); surface_factory_ = std::make_unique<HeadlessSurfaceFactory>(file_path_);
} }
private: private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment