diff options
author | Jason Ekstrand <jason.ekstrand@intel.com> | 2015-09-12 12:44:33 -0700 |
---|---|---|
committer | Jason Ekstrand <jason.ekstrand@intel.com> | 2015-09-12 12:44:33 -0700 |
commit | 107e2482c648acf7979086067a280b7782608154 (patch) | |
tree | 4ba40725b6e785728daff26d42805ebe8f8d9133 | |
parent | ec6bde2841a56da0d6a8328bdbc327bf6cbc1202 (diff) |
weston/vk: Add code to create an outputvulkan
-rw-r--r-- | src/vulkan-helpers.h | 1 | ||||
-rw-r--r-- | src/vulkan-renderer.c | 244 |
2 files changed, 240 insertions, 5 deletions
diff --git a/src/vulkan-helpers.h b/src/vulkan-helpers.h index 749d68af..a26ff886 100644 --- a/src/vulkan-helpers.h +++ b/src/vulkan-helpers.h @@ -40,6 +40,7 @@ __VK_HELP_STRUCT_NAME(ImageViewCreateInfo, IMAGE_VIEW_CREATE_INFO); __VK_HELP_STRUCT_NAME(InstanceCreateInfo, INSTANCE_CREATE_INFO); __VK_HELP_STRUCT_NAME(SurfaceDescriptionWindowWSI, SURFACE_DESCRIPTION_WINDOW_WSI); +__VK_HELP_STRUCT_NAME(SwapChainCreateInfoWSI, SWAP_CHAIN_CREATE_INFO_WSI); #define VK_STRUCT_DECL(StructName, name) \ Vk##StructName name = { __vulkan_helpers_##StructName##_type, NULL } diff --git a/src/vulkan-renderer.c b/src/vulkan-renderer.c index e0a9b03c..02a6b1c6 100644 --- a/src/vulkan-renderer.c +++ b/src/vulkan-renderer.c @@ -25,6 +25,8 @@ #define VK_PROTOTYPES +#include <assert.h> + #include <vulkan/vulkan.h> #include <vulkan/vk_wsi_swapchain.h> #include <vulkan/vk_wsi_device_swapchain.h> @@ -34,6 +36,8 @@ #include "vulkan-helpers.h" struct vk_renderer { + struct weston_renderer base; + VkInstance instance; VkPhysicalDevice physical_device; VkDevice device; @@ -42,16 +46,223 @@ struct vk_renderer { PFN_vkGetPhysicalDeviceSurfaceSupportWSI get_pd_surface_support; }; +static inline struct vk_renderer * +get_renderer(struct weston_compositor *wc) +{ + return (struct vk_renderer *)wc->renderer; +} + +struct vk_output_image { + VkImage image; +}; + +struct vk_output_state { + VkSwapChainWSI swap_chain; + + struct vk_output_image *images; + int num_images; +}; + +static inline struct vk_output_state * +get_output_state(struct weston_output *output) +{ + return (struct vk_output_state *)output->renderer_state; +} + static int -vk_renderer_output_create(struct weston_output *output, - VkSurfaceDescriptionWindowWSI *window, - VkFormat *formats, const int n_formats) -{ return -1; /* TODO */ } +vk_read_pixels(struct weston_output *output, + pixman_format_code_t format, void *pixels, + uint32_t x, uint32_t y, + uint32_t width, uint32_t height) +{ + return -1; /* TODO */ +} + +static void +vk_repaint_output(struct weston_output *output, + pixman_region32_t *output_damage) +{ /* TODO */ } + +static void +vk_flush_damage(struct weston_surface *surface) +{ /* TODO */ } + +static void +vk_attach(struct weston_surface *es, struct weston_buffer *buffer) +{ /* TODO */ } + +static void +vk_surface_set_color(struct weston_surface *surface, + float red, float green, float blue, float alpha) +{ /* TODO */ } + +/** See weston_surface_get_content_size() */ +static void +vk_surface_get_content_size(struct weston_surface *surface, + int *width, int *height) +{ /* TODO */ } + +/** See weston_surface_copy_content() */ +static int +vk_surface_copy_content(struct weston_surface *surface, + void *target, size_t size, + int src_x, int src_y, int width, int height) +{ + return -1; /* TODO */ +} + +/** See weston_compositor_import_dmabuf() */ +static bool +vk_import_dmabuf(struct weston_compositor *ec, + struct linux_dmabuf_buffer *buffer) +{ + return false; /* TODO */ +} static void vk_renderer_output_destroy(struct weston_output *output) { /* TODO */ } +static VkFormat +choose_format_for_window(struct vk_renderer *vkr, + VkSurfaceDescriptionWindowWSI *vk_window, + VkFormat *formats, const int n_formats) +{ + VkResult result; + size_t size; + VkSurfaceFormatPropertiesWSI *window_formats; + int i, j; + + result = vkGetSurfaceInfoWSI(vkr->device, + (VkSurfaceDescriptionWSI *)&vk_window, + VK_SURFACE_INFO_TYPE_FORMATS_WSI, + &size, NULL); + if (result != VK_SUCCESS || size == 0) + return VK_FORMAT_UNDEFINED; + + window_formats = malloc(size); + if (!window_formats) + return VK_FORMAT_UNDEFINED; + + result = vkGetSurfaceInfoWSI(vkr->device, + (VkSurfaceDescriptionWSI *)&vk_window, + VK_SURFACE_INFO_TYPE_FORMATS_WSI, + &size, window_formats); + if (result != VK_SUCCESS || size == 0) + goto fail; + + for (i = 0; i < n_formats; i++) { + for (j = 0; j < (int)(size / sizeof(*window_formats)); j++) { + if (formats[i] == window_formats[j].format) { + free(window_formats); + return formats[i]; + } + } + } + + /* No matching formats found */ + +fail: + free(window_formats); + return VK_FORMAT_UNDEFINED; +} + +static int +vk_renderer_output_create(struct weston_output *output, + VkSurfaceDescriptionWindowWSI *vk_window, + VkFormat *formats, const int n_formats) +{ + struct weston_compositor *wc = output->compositor; + struct vk_renderer *vkr = get_renderer(wc); + VkExtent2D output_size; + struct vk_output_state *os; + VkFormat format; + VkResult result; + VkSurfacePropertiesWSI vk_surface_props; + VkSwapChainImagePropertiesWSI *image_props; + size_t size; + + format = choose_format_for_window(vkr, vk_window, formats, n_formats); + if (format == VK_FORMAT_UNDEFINED) + return -1; + + size = sizeof(vk_surface_props); + result = vkGetSurfaceInfoWSI(vkr->device, + (VkSurfaceDescriptionWSI *)&vk_window, + VK_SURFACE_INFO_TYPE_PROPERTIES_WSI, + &size, &vk_surface_props); + assert(result == VK_SUCCESS); + + output_size.width = output->current_mode->width; + output_size.height = output->current_mode->height; + + /* Make sure the size is actually in bounds */ + if (vk_surface_props.minImageExtent.width > output_size.width || + vk_surface_props.minImageExtent.height > output_size.height || + (vk_surface_props.maxImageExtent.width > 0 && + vk_surface_props.maxImageExtent.width < output_size.width) || + (vk_surface_props.maxImageExtent.height > 0 && + vk_surface_props.maxImageExtent.height < output_size.height)) + return -1; + + /* TODO: Transforms */ + + os = zalloc(sizeof *os); + if (os == NULL) + return -1; + + VK_STRUCT(SwapChainCreateInfoWSI, sc_info, + s.pSurfaceDescription = (void *)vk_window, + s.minImageCount = vk_surface_props.minImageCount, + s.imageFormat = format, + s.imageExtent = output_size, + s.imageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + s.preTransform = VK_SURFACE_TRANSFORM_NONE_WSI, + s.imageArraySize = 1 + ); + + result = vkCreateSwapChainWSI(vkr->device, &sc_info, &os->swap_chain); + if (result != VK_SUCCESS) + goto fail_alloc; + + result = vkGetSwapChainInfoWSI(vkr->device, os->swap_chain, + VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI, + &size, NULL); + if (result != VK_SUCCESS || size == 0) + goto fail_swap_chain; + + os->num_images = size / sizeof(*image_props); + + image_props = malloc(size); + if (!image_props) + goto fail_swap_chain; + + result = vkGetSwapChainInfoWSI(vkr->device, os->swap_chain, + VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI, + &size, image_props); + assert(result == VK_SUCCESS); + assert(size == os->num_images * sizeof(*image_props)); + + os->images = malloc(os->num_images * sizeof(*os->images)); + if (os->images == NULL) + goto fail_image_props; + + for (int i = 0; i < os->num_images; i++) + os->images[i].image = image_props[i].image; + + free(image_props); + + return 0; + +fail_image_props: + free(image_props); +fail_swap_chain: + vkDestroySwapChainWSI(vkr->device, os->swap_chain); +fail_alloc: + free(os); + return -1; +} + static void vk_renderer_output_set_border(struct weston_output *output, enum vk_renderer_border_side side, @@ -142,8 +353,18 @@ const char *device_extensions[] = { "VK_WSI_device_swapchain", }; +static void +vk_renderer_destroy(struct weston_compositor *wc) +{ + struct vk_renderer *r = get_renderer(wc); + + vkDestroyDevice(r->device); + vkDestroyInstance(r->instance); + free(r); +} + static int -vk_renderer_create(struct weston_compositor *ec, VkPlatformWSI platform, +vk_renderer_create(struct weston_compositor *wc, VkPlatformWSI platform, void *native_platform_handle) { struct vk_renderer *r; @@ -204,6 +425,19 @@ vk_renderer_create(struct weston_compositor *ec, VkPlatformWSI platform, if (result != VK_SUCCESS) goto fail_device; + r->base.read_pixels = vk_read_pixels; + r->base.repaint_output = vk_repaint_output; + r->base.flush_damage = vk_flush_damage; + r->base.attach = vk_attach; + r->base.surface_set_color = vk_surface_set_color; + r->base.destroy = vk_renderer_destroy; + r->base.surface_get_content_size = vk_surface_get_content_size; + r->base.surface_copy_content = vk_surface_copy_content; + r->base.import_dmabuf = vk_import_dmabuf; + + wc->renderer = &r->base; + return 0; + fail_device: vkDestroyDevice(r->device); fail_instance: |