blob: 4846fbeddd6c286a1c244b02928331ec5bd2401a [file] [log] [blame]
// Copyright 2018 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/scenic/scenic_surface_factory.h"
#include <lib/zx/event.h>
#include "base/fuchsia/component_context.h"
#include "base/fuchsia/fuchsia_logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "ui/gfx/native_pixmap.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/vsync_provider.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/common/gl_ozone_egl.h"
#include "ui/ozone/platform/scenic/scenic_gpu_service.h"
#include "ui/ozone/platform/scenic/scenic_surface.h"
#include "ui/ozone/platform/scenic/scenic_window.h"
#include "ui/ozone/platform/scenic/scenic_window_canvas.h"
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h"
#endif
namespace ui {
namespace {
class GLOzoneEGLScenic : public GLOzoneEGL {
public:
GLOzoneEGLScenic() = default;
~GLOzoneEGLScenic() override = default;
// GLOzone:
scoped_refptr<gl::GLSurface> CreateViewGLSurface(
gfx::AcceleratedWidget window) override {
NOTIMPLEMENTED();
return nullptr;
}
scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(
const gfx::Size& size) override {
return gl::InitializeGLSurface(
base::MakeRefCounted<gl::PbufferGLSurfaceEGL>(size));
}
EGLNativeDisplayType GetNativeDisplay() override {
return EGL_DEFAULT_DISPLAY;
}
protected:
bool LoadGLES2Bindings(gl::GLImplementation implementation) override {
return LoadDefaultEGLGLES2Bindings(implementation);
}
private:
DISALLOW_COPY_AND_ASSIGN(GLOzoneEGLScenic);
};
// TODO(crbug.com/852011): Implement this class - currently it's just a stub.
class ScenicPixmap : public gfx::NativePixmap {
public:
explicit ScenicPixmap(gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format)
: size_(size), format_(format) {
NOTIMPLEMENTED();
}
bool AreDmaBufFdsValid() const override { return false; }
size_t GetDmaBufFdCount() const override { return 0; }
int GetDmaBufFd(size_t plane) const override { return -1; }
int GetDmaBufPitch(size_t plane) const override { return 0; }
int GetDmaBufOffset(size_t plane) const override { return 0; }
uint64_t GetDmaBufModifier(size_t plane) const override { return 0; }
gfx::BufferFormat GetBufferFormat() const override { return format_; }
gfx::Size GetBufferSize() const override { return size_; }
uint32_t GetUniqueId() const override { return 0; }
bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
int plane_z_order,
gfx::OverlayTransform plane_transform,
const gfx::Rect& display_bounds,
const gfx::RectF& crop_rect,
bool enable_blend,
std::unique_ptr<gfx::GpuFence> gpu_fence) override {
NOTIMPLEMENTED();
return false;
}
gfx::NativePixmapHandle ExportHandle() override {
NOTIMPLEMENTED();
return gfx::NativePixmapHandle();
}
private:
~ScenicPixmap() override {}
gfx::Size size_;
gfx::BufferFormat format_;
DISALLOW_COPY_AND_ASSIGN(ScenicPixmap);
};
} // namespace
ScenicSurfaceFactory::ScenicSurfaceFactory(ScenicWindowManager* window_manager)
: window_manager_(window_manager),
egl_implementation_(std::make_unique<GLOzoneEGLScenic>()) {}
ScenicSurfaceFactory::ScenicSurfaceFactory(ScenicGpuService* scenic_gpu_service)
: scenic_gpu_service_(scenic_gpu_service),
egl_implementation_(std::make_unique<GLOzoneEGLScenic>()) {}
ScenicSurfaceFactory::~ScenicSurfaceFactory() = default;
fuchsia::ui::scenic::Scenic* ScenicSurfaceFactory::GetScenic() {
if (!scenic_) {
scenic_ = base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::ui::scenic::Scenic>();
scenic_.set_error_handler([](zx_status_t status) {
ZX_LOG(FATAL, status) << "Scenic connection failed";
});
}
return scenic_.get();
}
std::vector<gl::GLImplementation>
ScenicSurfaceFactory::GetAllowedGLImplementations() {
// TODO(spang): Remove this after crbug.com/897208 is fixed.
return std::vector<gl::GLImplementation>{gl::kGLImplementationSwiftShaderGL};
}
GLOzone* ScenicSurfaceFactory::GetGLOzone(gl::GLImplementation implementation) {
switch (implementation) {
case gl::kGLImplementationSwiftShaderGL:
return egl_implementation_.get();
default:
return nullptr;
}
}
std::unique_ptr<PlatformWindowSurface>
ScenicSurfaceFactory::CreatePlatformWindowSurface(
gfx::AcceleratedWidget widget) {
return std::make_unique<ScenicSurface>(
this, GetScenic(), scenic_gpu_service_->gpu_host(), widget);
}
std::unique_ptr<SurfaceOzoneCanvas> ScenicSurfaceFactory::CreateCanvasForWidget(
gfx::AcceleratedWidget widget) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!window_manager_)
LOG(FATAL) << "Software output not supported from GPU process";
ScenicWindow* window = window_manager_->GetWindow(widget);
if (!window)
return nullptr;
return std::make_unique<ScenicWindowCanvas>(GetScenic(), window);
}
scoped_refptr<gfx::NativePixmap> ScenicSurfaceFactory::CreateNativePixmap(
gfx::AcceleratedWidget widget,
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage) {
return new ScenicPixmap(widget, size, format);
}
#if BUILDFLAG(ENABLE_VULKAN)
std::unique_ptr<gpu::VulkanImplementation>
ScenicSurfaceFactory::CreateVulkanImplementation() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (!scenic_gpu_service_)
LOG(FATAL) << "Vulkan implementation requires InitializeForGPU";
return std::make_unique<ui::VulkanImplementationScenic>(this);
}
#endif
void ScenicSurfaceFactory::AddSurface(gfx::AcceleratedWidget widget,
ScenicSurface* surface) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!base::ContainsKey(surface_map_, widget));
surface_map_.insert(std::make_pair(widget, surface));
}
void ScenicSurfaceFactory::RemoveSurface(gfx::AcceleratedWidget widget) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(base::ContainsKey(surface_map_, widget));
surface_map_.erase(widget);
}
ScenicSurface* ScenicSurfaceFactory::GetSurface(gfx::AcceleratedWidget widget) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto it = surface_map_.find(widget);
DCHECK(it != surface_map_.end());
return it->second;
}
} // namespace ui