display.cc 10 KB

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