Index: components/exo/wayland/server.cc |
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc |
index 84c17c1bfb9acfb2ff99527cd600b6093f3763ac..c17a7658a8624f14b7c900d700cb3bde313a80ea 100644 |
--- a/components/exo/wayland/server.cc |
+++ b/components/exo/wayland/server.cc |
@@ -653,19 +653,55 @@ void linux_buffer_params_add(wl_client* client, |
} |
} |
-void linux_buffer_params_create(wl_client* client, |
- wl_resource* resource, |
- int32_t width, |
- int32_t height, |
- uint32_t format, |
- uint32_t flags) { |
+bool ValidateLinuxBufferParams(wl_resource* resource, |
+ int32_t width, |
+ int32_t height, |
+ gfx::BufferFormat format, |
+ uint32_t flags) { |
if (width <= 0 || height <= 0) { |
wl_resource_post_error(resource, |
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS, |
"invalid width or height"); |
- return; |
+ return false; |
+ } |
+ |
+ if (flags & (ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT | |
+ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED)) { |
+ wl_resource_post_error(resource, |
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, |
+ "flags not supported"); |
+ return false; |
} |
+ LinuxBufferParams* linux_buffer_params = |
+ GetUserDataAs<LinuxBufferParams>(resource); |
+ size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format); |
+ |
+ for (uint32_t i = 0; i < num_planes; ++i) { |
+ auto plane_it = linux_buffer_params->planes.find(i); |
+ if (plane_it == linux_buffer_params->planes.end()) { |
+ wl_resource_post_error(resource, |
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, |
+ "missing a plane"); |
+ return false; |
+ } |
+ } |
+ |
+ if (linux_buffer_params->planes.size() != num_planes) { |
+ wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, |
+ "plane idx out of bounds"); |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+void linux_buffer_params_create(wl_client* client, |
+ wl_resource* resource, |
+ int32_t width, |
+ int32_t height, |
+ uint32_t format, |
+ uint32_t flags) { |
const auto* supported_format = std::find_if( |
std::begin(dmabuf_supported_formats), std::end(dmabuf_supported_formats), |
[format](const dmabuf_supported_format& supported_format) { |
@@ -678,13 +714,9 @@ void linux_buffer_params_create(wl_client* client, |
return; |
} |
- if (flags & (ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT | |
- ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED)) { |
- wl_resource_post_error(resource, |
- ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, |
- "flags not supported"); |
+ if (!ValidateLinuxBufferParams(resource, width, height, |
+ supported_format->buffer_format, flags)) |
return; |
- } |
LinuxBufferParams* linux_buffer_params = |
GetUserDataAs<LinuxBufferParams>(resource); |
@@ -692,23 +724,11 @@ void linux_buffer_params_create(wl_client* client, |
size_t num_planes = |
gfx::NumberOfPlanesForBufferFormat(supported_format->buffer_format); |
- if (linux_buffer_params->planes.size() != num_planes) { |
- wl_resource_post_error(resource, ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX, |
- "plane idx out of bounds"); |
- return; |
- } |
- |
std::vector<gfx::NativePixmapPlane> planes; |
std::vector<base::ScopedFD> fds; |
for (uint32_t i = 0; i < num_planes; ++i) { |
auto plane_it = linux_buffer_params->planes.find(i); |
- if (plane_it == linux_buffer_params->planes.end()) { |
- wl_resource_post_error(resource, |
- ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE, |
- "missing a plane"); |
- return; |
- } |
LinuxBufferParams::Plane& plane = plane_it->second; |
planes.emplace_back(plane.stride, plane.offset, 0, 0); |
fds.push_back(std::move(plane.fd)); |
@@ -734,10 +754,71 @@ void linux_buffer_params_create(wl_client* client, |
zwp_linux_buffer_params_v1_send_created(resource, buffer_resource); |
} |
+void linux_buffer_params_create_immed(wl_client* client, |
+ wl_resource* resource, |
+ uint32_t buffer_id, |
+ int32_t width, |
+ int32_t height, |
+ uint32_t format, |
+ uint32_t flags) { |
+ const auto* supported_format = std::find_if( |
+ std::begin(dmabuf_supported_formats), std::end(dmabuf_supported_formats), |
+ [format](const dmabuf_supported_format& supported_format) { |
+ return supported_format.dmabuf_format == format; |
+ }); |
+ if (supported_format == std::end(dmabuf_supported_formats)) { |
+ wl_resource_post_error(resource, |
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT, |
+ "format not supported"); |
+ return; |
+ } |
+ |
+ if (!ValidateLinuxBufferParams(resource, width, height, |
+ supported_format->buffer_format, flags)) |
+ return; |
+ |
+ LinuxBufferParams* linux_buffer_params = |
+ GetUserDataAs<LinuxBufferParams>(resource); |
+ |
+ size_t num_planes = |
+ gfx::NumberOfPlanesForBufferFormat(supported_format->buffer_format); |
+ |
+ std::vector<gfx::NativePixmapPlane> planes; |
+ std::vector<base::ScopedFD> fds; |
+ |
+ for (uint32_t i = 0; i < num_planes; ++i) { |
+ auto plane_it = linux_buffer_params->planes.find(i); |
+ LinuxBufferParams::Plane& plane = plane_it->second; |
+ planes.emplace_back(plane.stride, plane.offset, 0, 0); |
+ fds.push_back(std::move(plane.fd)); |
+ } |
+ |
+ std::unique_ptr<Buffer> buffer = |
+ linux_buffer_params->display->CreateLinuxDMABufBuffer( |
+ gfx::Size(width, height), supported_format->buffer_format, planes, |
+ std::move(fds)); |
+ if (!buffer) { |
+ // On import failure in case of a create_immed request, the protocol |
+ // allows us to raise a fatal error from zwp_linux_dmabuf_v1 version 2+. |
+ wl_resource_post_error(resource, |
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER, |
+ "dmabuf import failed"); |
+ return; |
+ } |
+ |
+ wl_resource* buffer_resource = |
+ wl_resource_create(client, &wl_buffer_interface, 1, buffer_id); |
+ |
+ buffer->set_release_callback(base::Bind(&HandleBufferReleaseCallback, |
+ base::Unretained(buffer_resource))); |
+ |
+ SetImplementation(buffer_resource, &buffer_implementation, std::move(buffer)); |
+} |
+ |
const struct zwp_linux_buffer_params_v1_interface |
- linux_buffer_params_implementation = {linux_buffer_params_destroy, |
- linux_buffer_params_add, |
- linux_buffer_params_create}; |
+ linux_buffer_params_implementation = { |
+ linux_buffer_params_destroy, linux_buffer_params_add, |
+ linux_buffer_params_create, linux_buffer_params_create_immed}; |
//////////////////////////////////////////////////////////////////////////////// |
// linux_dmabuf_interface: |
@@ -753,7 +834,7 @@ void linux_dmabuf_create_params(wl_client* client, |
base::MakeUnique<LinuxBufferParams>(GetUserDataAs<Display>(resource)); |
wl_resource* linux_buffer_params_resource = |
- wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, 1, id); |
+ wl_resource_create(client, &zwp_linux_buffer_params_v1_interface, 2, id); |
SetImplementation(linux_buffer_params_resource, |
&linux_buffer_params_implementation, |
@@ -768,7 +849,7 @@ void bind_linux_dmabuf(wl_client* client, |
uint32_t version, |
uint32_t id) { |
wl_resource* resource = |
- wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, 1, id); |
+ wl_resource_create(client, &zwp_linux_dmabuf_v1_interface, version, id); |
wl_resource_set_implementation(resource, &linux_dmabuf_implementation, data, |
nullptr); |
@@ -3943,7 +4024,7 @@ Server::Server(Display* display) |
#if defined(USE_OZONE) |
wl_global_create(wl_display_.get(), &wl_drm_interface, drm_version, display_, |
bind_drm); |
- wl_global_create(wl_display_.get(), &zwp_linux_dmabuf_v1_interface, 1, |
+ wl_global_create(wl_display_.get(), &zwp_linux_dmabuf_v1_interface, 2, |
display_, bind_linux_dmabuf); |
#endif |
wl_global_create(wl_display_.get(), &wl_subcompositor_interface, 1, display_, |