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