1 // Copyright 2015 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 "components/exo/display.h"
6
7 #include <iterator>
8 #include <memory>
9 #include <utility>
10
11 #include "base/command_line.h"
12 #include "base/trace_event/trace_event.h"
13 #include "base/trace_event/traced_value.h"
14 #include "build/build_config.h"
15 #include "components/exo/data_device.h"
16 #include "components/exo/file_helper.h"
17 #include "components/exo/input_method_surface_manager.h"
18 #include "components/exo/notification_surface.h"
19 #include "components/exo/notification_surface_manager.h"
20 #include "components/exo/shared_memory.h"
21 #include "components/exo/sub_surface.h"
22 #include "components/exo/surface.h"
23 #include "ui/gfx/linux/client_native_pixmap_factory_dmabuf.h"
24 #include "ui/views/widget/widget.h"
25 #include "ui/wm/core/coordinate_conversion.h"
26
27 #if defined(USE_OZONE)
28 #include <GLES2/gl2extchromium.h>
29 #include "components/exo/buffer.h"
30 #include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
31 #include "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h"
32 #include "third_party/khronos/GLES2/gl2.h"
33 #include "third_party/khronos/GLES2/gl2ext.h"
34 #include "ui/ozone/public/ozone_switches.h"
35 #endif
36
37 #if defined(OS_CHROMEOS)
38 #include "ash/public/cpp/shell_window_ids.h"
39 #include "ash/wm/desks/desks_util.h"
40 #include "components/exo/client_controlled_shell_surface.h"
41 #include "components/exo/input_method_surface.h"
42 #include "components/exo/shell_surface.h"
43 #include "components/exo/toast_surface.h"
44 #include "components/exo/toast_surface_manager.h"
45 #include "components/exo/xdg_shell_surface.h"
46 #endif
47
48 namespace exo {
49
50 ////////////////////////////////////////////////////////////////////////////////
51 // Display, public:
52
Display()53 Display::Display()
54 #if defined(USE_OZONE)
55 : client_native_pixmap_factory_(
56 gfx::CreateClientNativePixmapFactoryDmabuf())
57 #endif
58 {
59 }
60
61 #if defined(OS_CHROMEOS)
Display(std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,std::unique_ptr<ToastSurfaceManager> toast_surface_manager,std::unique_ptr<FileHelper> file_helper)62 Display::Display(
63 std::unique_ptr<NotificationSurfaceManager> notification_surface_manager,
64 std::unique_ptr<InputMethodSurfaceManager> input_method_surface_manager,
65 std::unique_ptr<ToastSurfaceManager> toast_surface_manager,
66 std::unique_ptr<FileHelper> file_helper)
67 : notification_surface_manager_(std::move(notification_surface_manager)),
68 input_method_surface_manager_(std::move(input_method_surface_manager)),
69 toast_surface_manager_(std::move(toast_surface_manager)),
70 file_helper_(std::move(file_helper)),
71 client_native_pixmap_factory_(
72 gfx::CreateClientNativePixmapFactoryDmabuf()) {}
73 #endif // defined(OS_CHROMEOS)
74
~Display()75 Display::~Display() {
76 Shutdown();
77 }
78
Shutdown()79 void Display::Shutdown() {
80 if (shutdown_)
81 return;
82 shutdown_ = true;
83 seat_.Shutdown();
84 }
85
CreateSurface()86 std::unique_ptr<Surface> Display::CreateSurface() {
87 TRACE_EVENT0("exo", "Display::CreateSurface");
88
89 return std::make_unique<Surface>();
90 }
91
CreateSharedMemory(base::UnsafeSharedMemoryRegion shared_memory_region)92 std::unique_ptr<SharedMemory> Display::CreateSharedMemory(
93 base::UnsafeSharedMemoryRegion shared_memory_region) {
94 TRACE_EVENT1("exo", "Display::CreateSharedMemory", "size",
95 shared_memory_region.GetSize());
96
97 if (!shared_memory_region.IsValid())
98 return nullptr;
99
100 return std::make_unique<SharedMemory>(std::move(shared_memory_region));
101 }
102
103 #if defined(USE_OZONE)
CreateLinuxDMABufBuffer(const gfx::Size & size,gfx::BufferFormat format,gfx::NativePixmapHandle handle,bool y_invert)104 std::unique_ptr<Buffer> Display::CreateLinuxDMABufBuffer(
105 const gfx::Size& size,
106 gfx::BufferFormat format,
107 gfx::NativePixmapHandle handle,
108 bool y_invert) {
109 TRACE_EVENT1("exo", "Display::CreateLinuxDMABufBuffer", "size",
110 size.ToString());
111
112 gfx::GpuMemoryBufferHandle gmb_handle;
113 gmb_handle.type = gfx::NATIVE_PIXMAP;
114 gmb_handle.native_pixmap_handle = std::move(handle);
115 std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer =
116 gpu::GpuMemoryBufferImplNativePixmap::CreateFromHandle(
117 client_native_pixmap_factory_.get(), std::move(gmb_handle), size,
118 format, gfx::BufferUsage::GPU_READ,
119 gpu::GpuMemoryBufferImpl::DestructionCallback());
120 if (!gpu_memory_buffer) {
121 LOG(ERROR) << "Failed to create GpuMemoryBuffer from handle";
122 return nullptr;
123 }
124
125 // Using zero-copy for optimal performance.
126 bool use_zero_copy = true;
127
128 return std::make_unique<Buffer>(
129 std::move(gpu_memory_buffer),
130 gpu::NativeBufferNeedsPlatformSpecificTextureTarget(format)
131 ? gpu::GetPlatformSpecificTextureTarget()
132 : GL_TEXTURE_2D,
133 // COMMANDS_COMPLETED queries are required by native pixmaps.
134 GL_COMMANDS_COMPLETED_CHROMIUM, use_zero_copy,
135 /*is_overlay_candidate=*/true, y_invert);
136 }
137 #endif // defined(USE_OZONE)
138
139 #if defined(OS_CHROMEOS)
CreateShellSurface(Surface * surface)140 std::unique_ptr<ShellSurface> Display::CreateShellSurface(Surface* surface) {
141 TRACE_EVENT1("exo", "Display::CreateShellSurface", "surface",
142 surface->AsTracedValue());
143 if (surface->HasSurfaceDelegate()) {
144 DLOG(ERROR) << "Surface has already been assigned a role";
145 return nullptr;
146 }
147
148 return std::make_unique<ShellSurface>(
149 surface, gfx::Point(), true /* activatable */, false /* can_minimize */,
150 ash::desks_util::GetActiveDeskContainerId());
151 }
152
CreateXdgShellSurface(Surface * surface)153 std::unique_ptr<XdgShellSurface> Display::CreateXdgShellSurface(
154 Surface* surface) {
155 TRACE_EVENT1("exo", "Display::CreateXdgShellSurface", "surface",
156 surface->AsTracedValue());
157 if (surface->HasSurfaceDelegate()) {
158 DLOG(ERROR) << "Surface has already been assigned a role";
159 return nullptr;
160 }
161
162 return std::make_unique<XdgShellSurface>(
163 surface, gfx::Point(), true /* activatable */, false /* can_minimize */,
164 ash::desks_util::GetActiveDeskContainerId());
165 }
166
167 std::unique_ptr<ClientControlledShellSurface>
CreateClientControlledShellSurface(Surface * surface,int container,double default_device_scale_factor,bool default_scale_cancellation)168 Display::CreateClientControlledShellSurface(Surface* surface,
169 int container,
170 double default_device_scale_factor,
171 bool default_scale_cancellation) {
172 TRACE_EVENT2("exo", "Display::CreateRemoteShellSurface", "surface",
173 surface->AsTracedValue(), "container", container);
174
175 if (surface->HasSurfaceDelegate()) {
176 DLOG(ERROR) << "Surface has already been assigned a role";
177 return nullptr;
178 }
179
180 // Remote shell surfaces in system modal container cannot be minimized.
181 bool can_minimize = container != ash::kShellWindowId_SystemModalContainer;
182
183 std::unique_ptr<ClientControlledShellSurface> shell_surface(
184 std::make_unique<ClientControlledShellSurface>(
185 surface, can_minimize, container, default_scale_cancellation));
186 if (default_scale_cancellation) {
187 shell_surface->SetScale(default_device_scale_factor);
188 shell_surface->CommitPendingScale();
189 }
190 return shell_surface;
191 }
192
CreateNotificationSurface(Surface * surface,const std::string & notification_key)193 std::unique_ptr<NotificationSurface> Display::CreateNotificationSurface(
194 Surface* surface,
195 const std::string& notification_key) {
196 TRACE_EVENT2("exo", "Display::CreateNotificationSurface", "surface",
197 surface->AsTracedValue(), "notification_key", notification_key);
198
199 if (!notification_surface_manager_ ||
200 notification_surface_manager_->GetSurface(notification_key)) {
201 DLOG(ERROR) << "Invalid notification key, key=" << notification_key;
202 return nullptr;
203 }
204
205 return std::make_unique<NotificationSurface>(
206 notification_surface_manager_.get(), surface, notification_key);
207 }
208
CreateInputMethodSurface(Surface * surface,double default_device_scale_factor,bool default_scale_cancellation)209 std::unique_ptr<InputMethodSurface> Display::CreateInputMethodSurface(
210 Surface* surface,
211 double default_device_scale_factor,
212 bool default_scale_cancellation) {
213 TRACE_EVENT1("exo", "Display::CreateInputMethodSurface", "surface",
214 surface->AsTracedValue());
215
216 if (!input_method_surface_manager_) {
217 DLOG(ERROR) << "Input method surface cannot be registered";
218 return nullptr;
219 }
220
221 if (surface->HasSurfaceDelegate()) {
222 DLOG(ERROR) << "Surface has already been assigned a role";
223 return nullptr;
224 }
225
226 std::unique_ptr<InputMethodSurface> input_method_surface(
227 std::make_unique<InputMethodSurface>(input_method_surface_manager_.get(),
228 surface,
229 default_scale_cancellation));
230 if (default_scale_cancellation) {
231 input_method_surface->SetScale(default_device_scale_factor);
232 input_method_surface->CommitPendingScale();
233 }
234 return input_method_surface;
235 }
236
CreateToastSurface(Surface * surface,double default_device_scale_factor,bool default_scale_cancellation)237 std::unique_ptr<ToastSurface> Display::CreateToastSurface(
238 Surface* surface,
239 double default_device_scale_factor,
240 bool default_scale_cancellation) {
241 TRACE_EVENT1("exo", "Display::CreateToastSurface", "surface",
242 surface->AsTracedValue());
243
244 if (!toast_surface_manager_) {
245 DLOG(ERROR) << "Toast surface cannot be registered";
246 return nullptr;
247 }
248
249 if (surface->HasSurfaceDelegate()) {
250 DLOG(ERROR) << "Surface has already been assigned a role";
251 return nullptr;
252 }
253
254 std::unique_ptr<ToastSurface> toast_surface(std::make_unique<ToastSurface>(
255 toast_surface_manager_.get(), surface, default_scale_cancellation));
256 if (default_scale_cancellation) {
257 toast_surface->SetScale(default_device_scale_factor);
258 toast_surface->CommitPendingScale();
259 }
260 return toast_surface;
261 }
262 #endif // defined(OS_CHROMEOS)
263
CreateSubSurface(Surface * surface,Surface * parent)264 std::unique_ptr<SubSurface> Display::CreateSubSurface(Surface* surface,
265 Surface* parent) {
266 TRACE_EVENT2("exo", "Display::CreateSubSurface", "surface",
267 surface->AsTracedValue(), "parent", parent->AsTracedValue());
268
269 if (surface->window()->Contains(parent->window())) {
270 DLOG(ERROR) << "Parent is contained within surface's hierarchy";
271 return nullptr;
272 }
273
274 if (surface->HasSurfaceDelegate()) {
275 DLOG(ERROR) << "Surface has already been assigned a role";
276 return nullptr;
277 }
278
279 return std::make_unique<SubSurface>(surface, parent);
280 }
281
CreateDataDevice(DataDeviceDelegate * delegate)282 std::unique_ptr<DataDevice> Display::CreateDataDevice(
283 DataDeviceDelegate* delegate) {
284 return std::make_unique<DataDevice>(delegate, seat(), file_helper_.get());
285 }
286
287 } // namespace exo
288