Hello, I am trying to make a vulkan based x11 compositor and I’ve got stuck.
I was able to load external memory, from a redirected window:
const redirected_window = xxx; // I've used xwininfo to grab a random window,
const redirected_pixmap = c.xcb_generate_id(conn);
_ = c.xcb_composite_redirect_window(conn, redirected_window, c.XCB_COMPOSITE_REDIRECT_MANUAL);
_ = c.xcb_composite_name_window_pixmap(conn, redirected_window, redirected_pixmap);
_ = c.xcb_flush(conn);
const buffer_from_pixmap_cookie = c.xcb_dri3_buffer_from_pixmap(conn, redirected_pixmap);
var xcb_error: ?*c.xcb_generic_error_t = null;
const buffer_from_pixmap_reply = c.xcb_dri3_buffer_from_pixmap_reply(conn, buffer_from_pixmap_cookie, &xcb_error);
std.debug.assert(xcb_error == null);
std.debug.assert(buffer_from_pixmap_reply.*.nfd == 1);
const redirected_fd: i32 = c.xcb_dri3_buffer_from_pixmap_reply_fds(conn, buffer_from_pixmap_reply)[0];
const import_memory_info = vk.ImportMemoryFdInfoKHR{ .fd = redirected_fd, .handle_type = vk.ExternalMemoryHandleTypeFlags{ .dma_buf_bit_ext = true } };
const memory_allocate_info = vk.MemoryAllocateInfo{
.p_next = &import_memory_info,
.allocation_size = buffer_from_pixmap_reply.*.size,
.memory_type_index = 0,
};
const redirected_memory = vkd.allocateMemory(device, &memory_allocate_info, null) catch |e| {
std.log.err("Couldn't import memory from redirected window, error: {}", .{e});
return;
};
defer vkd.freeMemory(device, redirected_memory, null);
I’ve included the source for that, because maybe I messed up something in this stage after all.
After importing the memory I’ve tried to create an image binded to that memory, but unfortunately I get an error from validation layer:
const external_memory_image_create_info = vk.ExternalMemoryImageCreateInfo{ .handle_types = .{ .dma_buf_bit_ext = true } };
const image_create_info = vk.ImageCreateInfo{ .p_next = &external_memory_image_create_info, .extent = vk.Extent3D{
.width = buffer_from_pixmap_reply.*.width,
.height = buffer_from_pixmap_reply.*.height,
.depth = 1,
}, .image_type = .@"2d", .mip_levels = 1, .array_layers = 1, .format = .b8g8r8a8_uint, .tiling = .optimal, .initial_layout = .undefined, .usage = vk.ImageUsageFlags{
.sampled_bit = true,
}, .sharing_mode = .exclusive, .samples = vk.SampleCountFlags{
.@"1_bit" = true,
}, .flags = vk.ImageCreateFlags{} };
const redirected_image = vkd.createImage(device, &image_create_info, null) catch |e| {
std.log.err("Couldn't create an image for redirected window buffer, error {}", .{e});
return;
};
vkd.bindImageMemory(device, redirected_image, redirected_memory, 0) catch |e| {
std.log.err("Couldn't bind the image to redirected window buffer, error {}", .{e});
return;
};
It says that this combination of format and other properties is unsupported, and it links to vkGetPhysicalDeviceImageFormatProperties2
. This function if I understand it properly takes a format, usage and so one at returns the valid handle types, but how do I get the supported formats in the first place and how do I know which of them is correct for the redirected window surface buffer?
I could try to iterate over the formats returned by vkGetPhysicalDeviceSurfaceFormatsKHR
but this doesn’t return the rest of the properties like tiling or flags, should I try every combination of those?