render/vulkan: drop unnecessary comments

Some comments in here are noise.
master
Simon Ser 2 years ago
parent 17b10746b4
commit d7bebb0a4c

@ -263,9 +263,6 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
.pNext = &modp, .pNext = &modp,
}; };
// the first call to vkGetPhysicalDeviceFormatProperties2 did only
// retrieve the number of modifiers, we now have to retrieve
// the modifiers
modp.pDrmFormatModifierProperties = modp.pDrmFormatModifierProperties =
calloc(modifier_count, sizeof(*modp.pDrmFormatModifierProperties)); calloc(modifier_count, sizeof(*modp.pDrmFormatModifierProperties));
if (!modp.pDrmFormatModifierProperties) { if (!modp.pDrmFormatModifierProperties) {

@ -71,8 +71,6 @@ static float color_to_linear(float non_linear) {
non_linear / 12.92; non_linear / 12.92;
} }
// renderer
// util
static void mat3_to_mat4(const float mat3[9], float mat4[4][4]) { static void mat3_to_mat4(const float mat3[9], float mat4[4][4]) {
memset(mat4, 0, sizeof(float) * 16); memset(mat4, 0, sizeof(float) * 16);
mat4[0][0] = mat3[0]; mat4[0][0] = mat3[0];
@ -578,7 +576,6 @@ static uint64_t end_command_buffer(struct wlr_vk_command_buffer *cb,
return cb->timeline_point; return cb->timeline_point;
} }
// buffer import
static void destroy_render_buffer(struct wlr_vk_render_buffer *buffer) { static void destroy_render_buffer(struct wlr_vk_render_buffer *buffer) {
wl_list_remove(&buffer->link); wl_list_remove(&buffer->link);
wlr_addon_finish(&buffer->addon); wlr_addon_finish(&buffer->addon);
@ -867,7 +864,6 @@ static struct wlr_vk_render_buffer *get_render_buffer(
return buffer; return buffer;
} }
// interface implementation
static bool vulkan_bind_buffer(struct wlr_renderer *wlr_renderer, static bool vulkan_bind_buffer(struct wlr_renderer *wlr_renderer,
struct wlr_buffer *wlr_buffer) { struct wlr_buffer *wlr_buffer) {
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
@ -1139,7 +1135,6 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
texture->transitioned = true; texture->transitioned = true;
} }
// acquire
acquire_barriers[idx] = (VkImageMemoryBarrier){ acquire_barriers[idx] = (VkImageMemoryBarrier){
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT, .srcQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT,
@ -1154,7 +1149,6 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
.subresourceRange.levelCount = 1, .subresourceRange.levelCount = 1,
}; };
// release
release_barriers[idx] = (VkImageMemoryBarrier){ release_barriers[idx] = (VkImageMemoryBarrier){
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.srcQueueFamilyIndex = renderer->dev->queue_family, .srcQueueFamilyIndex = renderer->dev->queue_family,
@ -1965,8 +1959,6 @@ static bool init_tex_layouts(struct wlr_vk_renderer *renderer,
VkResult res; VkResult res;
VkDevice dev = renderer->dev->dev; VkDevice dev = renderer->dev->dev;
// layouts
// descriptor set
VkDescriptorSetLayoutBinding ds_binding = { VkDescriptorSetLayoutBinding ds_binding = {
.binding = 0, .binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
@ -1987,7 +1979,6 @@ static bool init_tex_layouts(struct wlr_vk_renderer *renderer,
return false; return false;
} }
// pipeline layout
VkPushConstantRange pc_ranges[2] = { VkPushConstantRange pc_ranges[2] = {
{ {
.size = sizeof(struct vert_pcr_data), .size = sizeof(struct vert_pcr_data),
@ -2023,7 +2014,6 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer,
VkResult res; VkResult res;
VkDevice dev = renderer->dev->dev; VkDevice dev = renderer->dev->dev;
// layouts, descriptor set
VkDescriptorSetLayoutBinding ds_binding = { VkDescriptorSetLayoutBinding ds_binding = {
.binding = 0, .binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, .descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
@ -2092,7 +2082,6 @@ static bool init_tex_pipeline(struct wlr_vk_renderer *renderer,
.pData = &color_transform_type, .pData = &color_transform_type,
}; };
// shaders
VkPipelineShaderStageCreateInfo tex_stages[2] = { VkPipelineShaderStageCreateInfo tex_stages[2] = {
{ {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
@ -2109,7 +2098,6 @@ static bool init_tex_pipeline(struct wlr_vk_renderer *renderer,
}, },
}; };
// info
VkPipelineInputAssemblyStateCreateInfo assembly = { VkPipelineInputAssemblyStateCreateInfo assembly = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
@ -2187,8 +2175,6 @@ static bool init_tex_pipeline(struct wlr_vk_renderer *renderer,
.pVertexInputState = &vertex, .pVertexInputState = &vertex,
}; };
// NOTE: use could use a cache here for faster loading
// store it somewhere like $XDG_CACHE_HOME/wlroots/vk_pipe_cache
VkPipelineCache cache = VK_NULL_HANDLE; VkPipelineCache cache = VK_NULL_HANDLE;
res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, pipe); res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, pipe);
if (res != VK_SUCCESS) { if (res != VK_SUCCESS) {
@ -2204,7 +2190,6 @@ static bool init_blend_to_output_pipeline(struct wlr_vk_renderer *renderer,
VkResult res; VkResult res;
VkDevice dev = renderer->dev->dev; VkDevice dev = renderer->dev->dev;
// shaders
VkPipelineShaderStageCreateInfo tex_stages[2] = { VkPipelineShaderStageCreateInfo tex_stages[2] = {
{ {
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
@ -2220,7 +2205,6 @@ static bool init_blend_to_output_pipeline(struct wlr_vk_renderer *renderer,
}, },
}; };
// info
VkPipelineInputAssemblyStateCreateInfo assembly = { VkPipelineInputAssemblyStateCreateInfo assembly = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
@ -2291,8 +2275,6 @@ static bool init_blend_to_output_pipeline(struct wlr_vk_renderer *renderer,
.pVertexInputState = &vertex, .pVertexInputState = &vertex,
}; };
// NOTE: use could use a cache here for faster loading
// store it somewhere like $XDG_CACHE_HOME/wlroots/vk_pipe_cache
VkPipelineCache cache = VK_NULL_HANDLE; VkPipelineCache cache = VK_NULL_HANDLE;
res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, pipe); res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, pipe);
if (res != VK_SUCCESS) { if (res != VK_SUCCESS) {
@ -2362,7 +2344,6 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
return false; return false;
} }
// tex frags
sinfo = (VkShaderModuleCreateInfo){ sinfo = (VkShaderModuleCreateInfo){
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = sizeof(texture_frag_data), .codeSize = sizeof(texture_frag_data),
@ -2374,7 +2355,6 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
return false; return false;
} }
// quad frag
sinfo = (VkShaderModuleCreateInfo){ sinfo = (VkShaderModuleCreateInfo){
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = sizeof(quad_frag_data), .codeSize = sizeof(quad_frag_data),
@ -2386,7 +2366,6 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
return false; return false;
} }
// quad frag
sinfo = (VkShaderModuleCreateInfo){ sinfo = (VkShaderModuleCreateInfo){
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
.codeSize = sizeof(output_frag_data), .codeSize = sizeof(output_frag_data),
@ -2418,7 +2397,6 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
setup->render_format = format; setup->render_format = format;
// util
VkDevice dev = renderer->dev->dev; VkDevice dev = renderer->dev->dev;
VkResult res; VkResult res;
@ -2638,7 +2616,6 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
}, },
}; };
// info
VkPipelineInputAssemblyStateCreateInfo assembly = { VkPipelineInputAssemblyStateCreateInfo assembly = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
@ -2715,8 +2692,6 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
.pVertexInputState = &vertex, .pVertexInputState = &vertex,
}; };
// NOTE: use could use a cache here for faster loading
// store it somewhere like $XDG_CACHE_HOME/wlroots/vk_pipe_cache.bin
VkPipelineCache cache = VK_NULL_HANDLE; VkPipelineCache cache = VK_NULL_HANDLE;
res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, &setup->quad_pipe); res = vkCreateGraphicsPipelines(dev, cache, 1, &pinfo, NULL, &setup->quad_pipe);
if (res != VK_SUCCESS) { if (res != VK_SUCCESS) {
@ -2754,7 +2729,6 @@ struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev
goto error; goto error;
} }
// command pool
VkCommandPoolCreateInfo cpool_info = { VkCommandPoolCreateInfo cpool_info = {
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
@ -2796,9 +2770,6 @@ struct wlr_renderer *wlr_vk_renderer_create_with_drm_fd(int drm_fd) {
wlr_log(WLR_INFO, "Run with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation " wlr_log(WLR_INFO, "Run with VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation "
"to enable the validation layer"); "to enable the validation layer");
// NOTE: we could add functionality to allow the compositor passing its
// name and version to this function. Just use dummies until then,
// shouldn't be relevant to the driver anyways
struct wlr_vk_instance *ini = vulkan_instance_create(default_debug); struct wlr_vk_instance *ini = vulkan_instance_create(default_debug);
if (!ini) { if (!ini) {
wlr_log(WLR_ERROR, "creating vulkan instance for renderer failed"); wlr_log(WLR_ERROR, "creating vulkan instance for renderer failed");
@ -2812,7 +2783,6 @@ struct wlr_renderer *wlr_vk_renderer_create_with_drm_fd(int drm_fd) {
return NULL; return NULL;
} }
// queue families
uint32_t qfam_count; uint32_t qfam_count;
vkGetPhysicalDeviceQueueFamilyProperties(phdev, &qfam_count, NULL); vkGetPhysicalDeviceQueueFamilyProperties(phdev, &qfam_count, NULL);
VkQueueFamilyProperties queue_props[qfam_count]; VkQueueFamilyProperties queue_props[qfam_count];

@ -283,7 +283,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
texture->format = &fmt->format; texture->format = &fmt->format;
// create image
VkImageCreateInfo img_info = { VkImageCreateInfo img_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.imageType = VK_IMAGE_TYPE_2D, .imageType = VK_IMAGE_TYPE_2D,
@ -304,7 +303,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
goto error; goto error;
} }
// memory
VkMemoryRequirements mem_reqs; VkMemoryRequirements mem_reqs;
vkGetImageMemoryRequirements(dev, texture->image, &mem_reqs); vkGetImageMemoryRequirements(dev, texture->image, &mem_reqs);
@ -338,7 +336,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
assert(format_info); assert(format_info);
texture->has_alpha = format_info->has_alpha; texture->has_alpha = format_info->has_alpha;
// view
VkImageViewCreateInfo view_info = { VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
@ -367,7 +364,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
goto error; goto error;
} }
// descriptor
texture->ds_pool = vulkan_alloc_texture_ds(renderer, renderer->ds_layout, &texture->ds); texture->ds_pool = vulkan_alloc_texture_ds(renderer, renderer->ds_layout, &texture->ds);
if (!texture->ds_pool) { if (!texture->ds_pool) {
wlr_log(WLR_ERROR, "failed to allocate descriptor"); wlr_log(WLR_ERROR, "failed to allocate descriptor");
@ -389,7 +385,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL); vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
// write data
pixman_region32_t region; pixman_region32_t region;
pixman_region32_init_rect(&region, 0, 0, width, height); pixman_region32_init_rect(&region, 0, 0, width, height);
if (!write_pixels(texture, stride, &region, data, VK_IMAGE_LAYOUT_UNDEFINED, if (!write_pixels(texture, stride, &region, data, VK_IMAGE_LAYOUT_UNDEFINED,
@ -483,7 +478,6 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
return VK_NULL_HANDLE; return VK_NULL_HANDLE;
} }
// image
VkExternalMemoryHandleTypeFlagBits htype = VkExternalMemoryHandleTypeFlagBits htype =
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
@ -680,7 +674,6 @@ static struct wlr_vk_texture *vulkan_texture_from_dmabuf(
texture->has_alpha = format_info->has_alpha; texture->has_alpha = format_info->has_alpha;
} }
// view
VkImageViewCreateInfo view_info = { VkImageViewCreateInfo view_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
.viewType = VK_IMAGE_VIEW_TYPE_2D, .viewType = VK_IMAGE_VIEW_TYPE_2D,
@ -719,7 +712,6 @@ static struct wlr_vk_texture *vulkan_texture_from_dmabuf(
goto error; goto error;
} }
// descriptor
texture->ds_pool = vulkan_alloc_texture_ds(renderer, ds_layout, &texture->ds); texture->ds_pool = vulkan_alloc_texture_ds(renderer, ds_layout, &texture->ds);
if (!texture->ds_pool) { if (!texture->ds_pool) {
wlr_log(WLR_ERROR, "failed to allocate descriptor"); wlr_log(WLR_ERROR, "failed to allocate descriptor");

@ -80,8 +80,6 @@ static VkBool32 debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
return false; return false;
} }
// instance
struct wlr_vk_instance *vulkan_instance_create(bool debug) { struct wlr_vk_instance *vulkan_instance_create(bool debug) {
// we require vulkan 1.1 // we require vulkan 1.1
PFN_vkEnumerateInstanceVersion pfEnumInstanceVersion = PFN_vkEnumerateInstanceVersion pfEnumInstanceVersion =
@ -99,7 +97,6 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
return NULL; return NULL;
} }
// query extension support
uint32_t avail_extc = 0; uint32_t avail_extc = 0;
VkResult res; VkResult res;
res = vkEnumerateInstanceExtensionProperties(NULL, &avail_extc, NULL); res = vkEnumerateInstanceExtensionProperties(NULL, &avail_extc, NULL);
@ -121,7 +118,6 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
avail_ext_props[j].extensionName, avail_ext_props[j].specVersion); avail_ext_props[j].extensionName, avail_ext_props[j].specVersion);
} }
// create instance
struct wlr_vk_instance *ini = calloc(1, sizeof(*ini)); struct wlr_vk_instance *ini = calloc(1, sizeof(*ini));
if (!ini) { if (!ini) {
wlr_log_errno(WLR_ERROR, "allocation failed"); wlr_log_errno(WLR_ERROR, "allocation failed");
@ -187,7 +183,6 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
goto error; goto error;
} }
// debug callback
if (debug_utils_found) { if (debug_utils_found) {
ini->api.createDebugUtilsMessengerEXT = ini->api.createDebugUtilsMessengerEXT =
(PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr( (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(
@ -228,7 +223,6 @@ void vulkan_instance_destroy(struct wlr_vk_instance *ini) {
free(ini); free(ini);
} }
// physical device matching
static void log_phdev(const VkPhysicalDeviceProperties *props) { static void log_phdev(const VkPhysicalDeviceProperties *props) {
uint32_t vv_major = VK_VERSION_MAJOR(props->apiVersion); uint32_t vv_major = VK_VERSION_MAJOR(props->apiVersion);
uint32_t vv_minor = VK_VERSION_MINOR(props->apiVersion); uint32_t vv_minor = VK_VERSION_MINOR(props->apiVersion);
@ -429,7 +423,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
VkPhysicalDevice phdev) { VkPhysicalDevice phdev) {
VkResult res; VkResult res;
// check for extensions
uint32_t avail_extc = 0; uint32_t avail_extc = 0;
res = vkEnumerateDeviceExtensionProperties(phdev, NULL, res = vkEnumerateDeviceExtensionProperties(phdev, NULL,
&avail_extc, NULL); &avail_extc, NULL);
@ -451,7 +444,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
avail_ext_props[j].extensionName, avail_ext_props[j].specVersion); avail_ext_props[j].extensionName, avail_ext_props[j].specVersion);
} }
// create device
struct wlr_vk_device *dev = calloc(1, sizeof(*dev)); struct wlr_vk_device *dev = calloc(1, sizeof(*dev));
if (!dev) { if (!dev) {
wlr_log_errno(WLR_ERROR, "allocation failed"); wlr_log_errno(WLR_ERROR, "allocation failed");
@ -485,7 +477,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
} }
} }
// queue families
{ {
uint32_t qfam_count; uint32_t qfam_count;
vkGetPhysicalDeviceQueueFamilyProperties(phdev, &qfam_count, NULL); vkGetPhysicalDeviceQueueFamilyProperties(phdev, &qfam_count, NULL);
@ -502,7 +493,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
break; break;
} }
} }
assert(graphics_found); assert(graphics_found);
} }
@ -601,7 +591,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini,
load_device_proc(dev, "vkImportSemaphoreFdKHR", &dev->api.vkImportSemaphoreFdKHR); load_device_proc(dev, "vkImportSemaphoreFdKHR", &dev->api.vkImportSemaphoreFdKHR);
load_device_proc(dev, "vkQueueSubmit2KHR", &dev->api.vkQueueSubmit2KHR); load_device_proc(dev, "vkQueueSubmit2KHR", &dev->api.vkQueueSubmit2KHR);
// - check device format support -
size_t max_fmts; size_t max_fmts;
const struct wlr_vk_format *fmts = vulkan_get_format_list(&max_fmts); const struct wlr_vk_format *fmts = vulkan_get_format_list(&max_fmts);
dev->shm_formats = calloc(max_fmts, sizeof(*dev->shm_formats)); dev->shm_formats = calloc(max_fmts, sizeof(*dev->shm_formats));

Loading…
Cancel
Save