1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/ozone/platform/wayland/gpu/wayland_surface_factory.h"
6 
7 #include <memory>
8 
9 #include "base/memory/ptr_util.h"
10 #include "ui/gfx/linux/client_native_pixmap_dmabuf.h"
11 #include "ui/ozone/common/egl_util.h"
12 #include "ui/ozone/common/gl_ozone_egl.h"
13 #include "ui/ozone/platform/wayland/common/wayland_object.h"
14 #include "ui/ozone/platform/wayland/gpu/gl_surface_egl_readback_wayland.h"
15 #include "ui/ozone/platform/wayland/gpu/gl_surface_wayland.h"
16 #include "ui/ozone/platform/wayland/gpu/wayland_buffer_manager_gpu.h"
17 #include "ui/ozone/platform/wayland/gpu/wayland_canvas_surface.h"
18 #include "ui/ozone/platform/wayland/host/wayland_connection.h"
19 #include "ui/ozone/platform/wayland/host/wayland_window.h"
20 #include "ui/ozone/platform/wayland/host/wayland_window_manager.h"
21 
22 #if defined(WAYLAND_GBM)
23 #include "ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.h"
24 #include "ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h"
25 #include "ui/ozone/public/ozone_platform.h"
26 #endif
27 
28 #if BUILDFLAG(ENABLE_VULKAN)
29 #include "ui/ozone/platform/wayland/gpu/vulkan_implementation_wayland.h"
30 #endif
31 
32 namespace ui {
33 
34 namespace {
35 
36 class GLOzoneEGLWayland : public GLOzoneEGL {
37  public:
GLOzoneEGLWayland(WaylandConnection * connection,WaylandBufferManagerGpu * buffer_manager)38   GLOzoneEGLWayland(WaylandConnection* connection,
39                     WaylandBufferManagerGpu* buffer_manager)
40       : connection_(connection), buffer_manager_(buffer_manager) {}
~GLOzoneEGLWayland()41   ~GLOzoneEGLWayland() override {}
42 
43   scoped_refptr<gl::GLSurface> CreateViewGLSurface(
44       gfx::AcceleratedWidget widget) override;
45 
46   scoped_refptr<gl::GLSurface> CreateSurfacelessViewGLSurface(
47       gfx::AcceleratedWidget window) override;
48 
49   scoped_refptr<gl::GLSurface> CreateOffscreenGLSurface(
50       const gfx::Size& size) override;
51 
52  protected:
53   gl::EGLDisplayPlatform GetNativeDisplay() override;
54   bool LoadGLES2Bindings(gl::GLImplementation impl) override;
55 
56  private:
57   WaylandConnection* const connection_;
58   WaylandBufferManagerGpu* const buffer_manager_;
59 
60   DISALLOW_COPY_AND_ASSIGN(GLOzoneEGLWayland);
61 };
62 
CreateViewGLSurface(gfx::AcceleratedWidget widget)63 scoped_refptr<gl::GLSurface> GLOzoneEGLWayland::CreateViewGLSurface(
64     gfx::AcceleratedWidget widget) {
65   // Only EGLGLES2 is supported with surfaceless view gl.
66   if ((gl::GetGLImplementation() != gl::kGLImplementationEGLGLES2) ||
67       !connection_)
68     return nullptr;
69 
70   WaylandWindow* window =
71       connection_->wayland_window_manager()->GetWindow(widget);
72   if (!window)
73     return nullptr;
74 
75   // The wl_egl_window needs to be created before the GLSurface so it can be
76   // used in the GLSurface constructor.
77   auto egl_window = CreateWaylandEglWindow(window);
78   if (!egl_window)
79     return nullptr;
80   return gl::InitializeGLSurface(new GLSurfaceWayland(std::move(egl_window)));
81 }
82 
CreateSurfacelessViewGLSurface(gfx::AcceleratedWidget window)83 scoped_refptr<gl::GLSurface> GLOzoneEGLWayland::CreateSurfacelessViewGLSurface(
84     gfx::AcceleratedWidget window) {
85   if (gl::GetGLImplementation() == gl::kGLImplementationSwiftShaderGL) {
86     return gl::InitializeGLSurface(
87         base::MakeRefCounted<GLSurfaceEglReadbackWayland>(window,
88                                                           buffer_manager_));
89   } else {
90 #if defined(WAYLAND_GBM)
91   // If there is a gbm device available, use surfaceless gl surface.
92   if (!buffer_manager_->gbm_device())
93     return nullptr;
94   return gl::InitializeGLSurface(
95       new GbmSurfacelessWayland(buffer_manager_, window));
96 #else
97   return nullptr;
98 #endif
99   }
100 }
101 
CreateOffscreenGLSurface(const gfx::Size & size)102 scoped_refptr<gl::GLSurface> GLOzoneEGLWayland::CreateOffscreenGLSurface(
103     const gfx::Size& size) {
104   if (gl::GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
105       size.width() == 0 && size.height() == 0) {
106     return gl::InitializeGLSurface(new gl::SurfacelessEGL(size));
107   } else {
108     return gl::InitializeGLSurface(new gl::PbufferGLSurfaceEGL(size));
109   }
110 }
111 
GetNativeDisplay()112 gl::EGLDisplayPlatform GLOzoneEGLWayland::GetNativeDisplay() {
113   if (connection_)
114     return gl::EGLDisplayPlatform(
115         reinterpret_cast<EGLNativeDisplayType>(connection_->display()));
116   return gl::EGLDisplayPlatform(EGL_DEFAULT_DISPLAY);
117 }
118 
LoadGLES2Bindings(gl::GLImplementation impl)119 bool GLOzoneEGLWayland::LoadGLES2Bindings(gl::GLImplementation impl) {
120   // TODO: It may not be necessary to set this environment variable when using
121   // swiftshader.
122   setenv("EGL_PLATFORM", "wayland", 0);
123   return LoadDefaultEGLGLES2Bindings(impl);
124 }
125 
126 }  // namespace
127 
WaylandSurfaceFactory(WaylandConnection * connection,WaylandBufferManagerGpu * buffer_manager)128 WaylandSurfaceFactory::WaylandSurfaceFactory(
129     WaylandConnection* connection,
130     WaylandBufferManagerGpu* buffer_manager)
131     : connection_(connection), buffer_manager_(buffer_manager) {
132   egl_implementation_ =
133       std::make_unique<GLOzoneEGLWayland>(connection_, buffer_manager_);
134 }
135 
136 WaylandSurfaceFactory::~WaylandSurfaceFactory() = default;
137 
138 std::unique_ptr<SurfaceOzoneCanvas>
CreateCanvasForWidget(gfx::AcceleratedWidget widget)139 WaylandSurfaceFactory::CreateCanvasForWidget(gfx::AcceleratedWidget widget) {
140   return std::make_unique<WaylandCanvasSurface>(buffer_manager_, widget);
141 }
142 
143 std::vector<gl::GLImplementation>
GetAllowedGLImplementations()144 WaylandSurfaceFactory::GetAllowedGLImplementations() {
145   std::vector<gl::GLImplementation> impls;
146   if (egl_implementation_) {
147     impls.push_back(gl::kGLImplementationEGLGLES2);
148     impls.push_back(gl::kGLImplementationSwiftShaderGL);
149   }
150   return impls;
151 }
152 
GetGLOzone(gl::GLImplementation implementation)153 GLOzone* WaylandSurfaceFactory::GetGLOzone(
154     gl::GLImplementation implementation) {
155   switch (implementation) {
156     case gl::kGLImplementationEGLGLES2:
157     case gl::kGLImplementationSwiftShaderGL:
158       return egl_implementation_.get();
159     default:
160       return nullptr;
161   }
162 }
163 
164 #if BUILDFLAG(ENABLE_VULKAN)
165 std::unique_ptr<gpu::VulkanImplementation>
CreateVulkanImplementation(bool allow_protected_memory,bool enforce_protected_memory)166 WaylandSurfaceFactory::CreateVulkanImplementation(
167     bool allow_protected_memory,
168     bool enforce_protected_memory) {
169   return std::make_unique<VulkanImplementationWayland>();
170 }
171 #endif
172 
CreateNativePixmap(gfx::AcceleratedWidget widget,VkDevice vk_device,gfx::Size size,gfx::BufferFormat format,gfx::BufferUsage usage,base::Optional<gfx::Size> framebuffer_size)173 scoped_refptr<gfx::NativePixmap> WaylandSurfaceFactory::CreateNativePixmap(
174     gfx::AcceleratedWidget widget,
175     VkDevice vk_device,
176     gfx::Size size,
177     gfx::BufferFormat format,
178     gfx::BufferUsage usage,
179     base::Optional<gfx::Size> framebuffer_size) {
180   DCHECK(!framebuffer_size || framebuffer_size == size);
181 #if defined(WAYLAND_GBM)
182   scoped_refptr<GbmPixmapWayland> pixmap =
183       base::MakeRefCounted<GbmPixmapWayland>(buffer_manager_);
184 
185   if (widget != gfx::kNullAcceleratedWidget)
186     pixmap->SetAcceleratedWiget(widget);
187 
188   if (!pixmap->InitializeBuffer(size, format, usage))
189     return nullptr;
190   return pixmap;
191 #else
192   return nullptr;
193 #endif
194 }
195 
CreateNativePixmapAsync(gfx::AcceleratedWidget widget,VkDevice vk_device,gfx::Size size,gfx::BufferFormat format,gfx::BufferUsage usage,NativePixmapCallback callback)196 void WaylandSurfaceFactory::CreateNativePixmapAsync(
197     gfx::AcceleratedWidget widget,
198     VkDevice vk_device,
199     gfx::Size size,
200     gfx::BufferFormat format,
201     gfx::BufferUsage usage,
202     NativePixmapCallback callback) {
203   // CreateNativePixmap is non-blocking operation. Thus, it is safe to call it
204   // and return the result with the provided callback.
205   std::move(callback).Run(
206       CreateNativePixmap(widget, vk_device, size, format, usage));
207 }
208 
209 scoped_refptr<gfx::NativePixmap>
CreateNativePixmapFromHandle(gfx::AcceleratedWidget widget,gfx::Size size,gfx::BufferFormat format,gfx::NativePixmapHandle handle)210 WaylandSurfaceFactory::CreateNativePixmapFromHandle(
211     gfx::AcceleratedWidget widget,
212     gfx::Size size,
213     gfx::BufferFormat format,
214     gfx::NativePixmapHandle handle) {
215   NOTIMPLEMENTED();
216   return nullptr;
217 }
218 
219 }  // namespace ui
220