summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Ekstrand <jason.ekstrand@intel.com>2015-09-12 12:44:33 -0700
committerJason Ekstrand <jason.ekstrand@intel.com>2015-09-12 12:44:33 -0700
commit107e2482c648acf7979086067a280b7782608154 (patch)
tree4ba40725b6e785728daff26d42805ebe8f8d9133
parentec6bde2841a56da0d6a8328bdbc327bf6cbc1202 (diff)
weston/vk: Add code to create an outputvulkan
-rw-r--r--src/vulkan-helpers.h1
-rw-r--r--src/vulkan-renderer.c244
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: