blob: 788d9e5256959595f18ffe02fa1db3d94ada280a [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "vk_surface.h"
#include "vk_utils.h"
// "vk_surface.h" only includes <vulkan/vulkan_core.h> and
// we need the Fuchsia-specific declarations as well here.
#include <stdio.h>
#include <stdlib.h>
#include <vulkan/vulkan.h>
//
//
//
bool
vk_physical_device_supports_presentation(VkInstance instance,
VkPhysicalDevice physical_device,
uint32_t queue_family_index)
{
// On Fuchsia, all physical devices support presentation and there is
// no Vulkan extension (yet?) to query support for it anyway.
return true;
}
void
vk_surface_get_requirements(bool disable_vsync, vk_surface_requirements_t * reqs)
{
reqs->num_layers = 1;
reqs->num_extensions = 1;
const char * layer_name = disable_vsync ? "VK_LAYER_FUCHSIA_imagepipe_swapchain_fb_skip_present"
: "VK_LAYER_FUCHSIA_imagepipe_swapchain_fb";
#if MAX_VK_SURFACE_REQUIREMENTS_STORAGE < 2
#error "Please increment MAX_VK_SURFACE_REQUIREMENTS_STORAGE to at least 2"
#endif
auto * storage = reinterpret_cast<const char **>(reqs->storage);
storage[0] = layer_name;
storage[1] = VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME;
reqs->layer_names = storage;
reqs->extension_names = storage + 1;
}
//
// vk_surface_t
//
struct vk_surface
{
VkSurfaceKHR surface_khr;
VkInstance instance;
const VkAllocationCallbacks * allocator;
};
vk_surface_t *
vk_surface_create(const vk_surface_config_t * config)
{
#define DEFINE_VULKAN_ENTRY_POINT(instance_, name_) \
PFN_##name_ name_ = (PFN_##name_)vkGetInstanceProcAddr(instance_, #name_); \
if (!name_) \
{ \
fprintf(stderr, "ERROR: Missing %s Vulkan entry point!\n", #name_); \
}
DEFINE_VULKAN_ENTRY_POINT(config->instance, vkCreateImagePipeSurfaceFUCHSIA)
if (!vkCreateImagePipeSurfaceFUCHSIA)
return NULL;
#undef DEFINE_VULKAN_ENTRY_POINT
uint32_t window_width = config->window_width;
uint32_t window_height = config->window_height;
if (!window_width)
window_width = 32;
if (!window_height)
window_height = 32;
VkImagePipeSurfaceCreateInfoFUCHSIA const surface_info = {
.sType = VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA,
.pNext = NULL,
};
VkSurfaceKHR surface_khr = VK_NULL_HANDLE;
VkResult ret = vkCreateImagePipeSurfaceFUCHSIA(config->instance,
&surface_info,
config->allocator,
&surface_khr);
if (ret != VK_SUCCESS)
{
fprintf(stderr,
"ERROR: Could not create Vulkan presentation surface: %s\n",
vk_result_to_string(ret));
return NULL;
}
vk_surface_t * result = reinterpret_cast<vk_surface_t *>(malloc(sizeof(*result)));
*result = (vk_surface_t){
.surface_khr = surface_khr,
.instance = config->instance,
.allocator = config->allocator,
};
return result;
}
VkSurfaceKHR
vk_surface_get_surface_khr(const vk_surface_t * surface)
{
return surface->surface_khr;
}
bool
vk_surface_poll_events(vk_surface_t * surface)
{
// TODO(digit): Find a way to receive events from the system.
return true;
}
void
vk_surface_destroy(vk_surface_t * surface)
{
if (surface)
{
if (surface->surface_khr != VK_NULL_HANDLE)
{
vkDestroySurfaceKHR(surface->instance, surface->surface_khr, surface->allocator);
surface->surface_khr = VK_NULL_HANDLE;
surface->instance = VK_NULL_HANDLE;
surface->allocator = NULL;
}
free(surface);
}
}