| // 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 |