wl_shm.cc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2019 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/wayland/wl_shm.h"
  5. #include <wayland-server-protocol-core.h>
  6. #include "base/bind.h"
  7. #include "components/exo/buffer.h"
  8. #include "components/exo/display.h"
  9. #include "components/exo/shared_memory.h"
  10. #include "components/exo/wayland/server_util.h"
  11. namespace exo {
  12. namespace wayland {
  13. namespace {
  14. void buffer_destroy(wl_client* client, wl_resource* resource) {
  15. wl_resource_destroy(resource);
  16. }
  17. const struct wl_buffer_interface buffer_implementation = {buffer_destroy};
  18. void HandleBufferReleaseCallback(wl_resource* resource) {
  19. wl_buffer_send_release(resource);
  20. wl_client_flush(wl_resource_get_client(resource));
  21. }
  22. const struct shm_supported_format {
  23. uint32_t shm_format;
  24. gfx::BufferFormat buffer_format;
  25. } shm_supported_formats[] = {
  26. {WL_SHM_FORMAT_XBGR8888, gfx::BufferFormat::RGBX_8888},
  27. {WL_SHM_FORMAT_ABGR8888, gfx::BufferFormat::RGBA_8888},
  28. {WL_SHM_FORMAT_XRGB8888, gfx::BufferFormat::BGRX_8888},
  29. {WL_SHM_FORMAT_ARGB8888, gfx::BufferFormat::BGRA_8888}};
  30. void shm_pool_create_buffer(wl_client* client,
  31. wl_resource* resource,
  32. uint32_t id,
  33. int32_t offset,
  34. int32_t width,
  35. int32_t height,
  36. int32_t stride,
  37. uint32_t format) {
  38. const auto* supported_format =
  39. std::find_if(shm_supported_formats,
  40. shm_supported_formats + std::size(shm_supported_formats),
  41. [format](const shm_supported_format& supported_format) {
  42. return supported_format.shm_format == format;
  43. });
  44. if (supported_format ==
  45. (shm_supported_formats + std::size(shm_supported_formats))) {
  46. wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
  47. "invalid format 0x%x", format);
  48. return;
  49. }
  50. if (offset < 0) {
  51. wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FORMAT,
  52. "invalid offset %d", offset);
  53. return;
  54. }
  55. std::unique_ptr<Buffer> buffer =
  56. GetUserDataAs<SharedMemory>(resource)->CreateBuffer(
  57. gfx::Size(width, height), supported_format->buffer_format, offset,
  58. stride);
  59. if (!buffer) {
  60. wl_resource_post_no_memory(resource);
  61. return;
  62. }
  63. wl_resource* buffer_resource =
  64. wl_resource_create(client, &wl_buffer_interface, 1, id);
  65. buffer->set_release_callback(base::BindRepeating(
  66. &HandleBufferReleaseCallback, base::Unretained(buffer_resource)));
  67. SetImplementation(buffer_resource, &buffer_implementation, std::move(buffer));
  68. }
  69. void shm_pool_destroy(wl_client* client, wl_resource* resource) {
  70. wl_resource_destroy(resource);
  71. }
  72. void shm_pool_resize(wl_client* client, wl_resource* resource, int32_t size) {
  73. auto* shm = GetUserDataAs<SharedMemory>(resource);
  74. if (size < 0 || static_cast<size_t>(size) < shm->GetSize()) {
  75. wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
  76. "Can't shrink a shm pool.");
  77. }
  78. if (!shm->Resize(size))
  79. wl_resource_post_no_memory(resource);
  80. }
  81. const struct wl_shm_pool_interface shm_pool_implementation = {
  82. shm_pool_create_buffer, shm_pool_destroy, shm_pool_resize};
  83. void shm_create_pool(wl_client* client,
  84. wl_resource* resource,
  85. uint32_t id,
  86. int fd,
  87. int32_t size) {
  88. static const auto kMode =
  89. base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe;
  90. auto fd_pair = base::subtle::ScopedFDPair(base::ScopedFD(fd),
  91. base::ScopedFD() /* readonly_fd */);
  92. auto guid = base::UnguessableToken::Create();
  93. auto platform_shared_memory = base::subtle::PlatformSharedMemoryRegion::Take(
  94. std::move(fd_pair), kMode, size, guid);
  95. std::unique_ptr<SharedMemory> shared_memory =
  96. GetUserDataAs<Display>(resource)->CreateSharedMemory(
  97. base::UnsafeSharedMemoryRegion::Deserialize(
  98. std::move(platform_shared_memory)));
  99. if (!shared_memory) {
  100. wl_resource_post_no_memory(resource);
  101. return;
  102. }
  103. wl_resource* shm_pool_resource =
  104. wl_resource_create(client, &wl_shm_pool_interface, 1, id);
  105. SetImplementation(shm_pool_resource, &shm_pool_implementation,
  106. std::move(shared_memory));
  107. }
  108. const struct wl_shm_interface shm_implementation = {shm_create_pool};
  109. } // namespace
  110. void bind_shm(wl_client* client, void* data, uint32_t version, uint32_t id) {
  111. wl_resource* resource = wl_resource_create(client, &wl_shm_interface, 1, id);
  112. wl_resource_set_implementation(resource, &shm_implementation, data, nullptr);
  113. for (const auto& supported_format : shm_supported_formats)
  114. wl_shm_send_format(resource, supported_format.shm_format);
  115. }
  116. } // namespace wayland
  117. } // namespace exo