spec: Add support for VK_KHR_incremental_present
[platform/core/uifw/vulkan-wsi-tizen.git] / src / wsi / extensions.c
1 /*
2  * Copyright © 2016 S-Core Corporation
3  * Copyright © 2016-2017 Samsung Electronics co., Ltd. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include "wsi.h"
26 #include <string.h>
27
28 VKAPI_ATTR VkResult VKAPI_CALL
29 vk_EnumerateInstanceExtensionProperties(const char                              *layer_name,
30                                                                                 uint32_t                                *count,
31                                                                                 VkExtensionProperties   *extensions)
32 {
33         vk_icd_t *icd = vk_get_icd();
34
35         if (!extensions) {
36                 *count = icd->instance_extension_count;
37                 return VK_SUCCESS;
38         }
39
40         *count = MIN(*count, icd->instance_extension_count);
41         memcpy(extensions, icd->instance_extensions, *count * sizeof(VkExtensionProperties));
42
43         if (*count < icd->instance_extension_count)
44                 return VK_INCOMPLETE;
45
46         return VK_SUCCESS;
47 }
48
49 static const VkExtensionProperties wsi_device_extensions[] = {
50         { VK_KHR_SWAPCHAIN_EXTENSION_NAME, 67 },
51         { VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, 1 },
52 };
53
54 VKAPI_ATTR VkResult VKAPI_CALL
55 vk_EnumerateDeviceExtensionProperties(VkPhysicalDevice           pdev,
56                                                                           const char                    *layer_name,
57                                                                           uint32_t                              *count,
58                                                                           VkExtensionProperties *extensions)
59 {
60         vk_icd_t        *icd = vk_get_icd();
61         uint32_t         max_ext_count, remaining, copied = 0;
62         VkResult         result;
63         uint32_t i, j, copy_count = 0;
64
65         result = icd->enum_dev_exts(pdev, layer_name, &max_ext_count, NULL);
66         VK_CHECK(result == VK_SUCCESS, return VK_ERROR_OUT_OF_HOST_MEMORY,
67                          "vkEnumerateDeviceExtensionProperties() failed.\n");
68
69         if (!extensions) {
70                 /*
71                  * for CTS fail return count
72                  * loader remove duplicates extension
73                  * second called count is not same when extensions has duplicate entry
74                  */
75                 VkExtensionProperties   *device_extensions =
76                         vk_alloc(vk_get_allocator(NULL, NULL),
77                                          max_ext_count * sizeof(VkExtensionProperties),
78                                          VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
79                 VK_CHECK(device_extensions, return VK_ERROR_OUT_OF_HOST_MEMORY, "malloc failed().\n");
80
81                 result = icd->enum_dev_exts(pdev, layer_name, &max_ext_count, device_extensions);
82                 VK_CHECK(result == VK_SUCCESS, return VK_ERROR_OUT_OF_HOST_MEMORY,
83                                  "vkEnumerateDeviceExtensionProperties() failed.\n");
84
85                 for (i = 0; i < ARRAY_LENGTH(wsi_device_extensions); i++) {
86                         for (j = 0; j < max_ext_count; j++) {
87                                 if (strcmp(device_extensions[j].extensionName,
88                                                    wsi_device_extensions[i].extensionName) == 0) {
89                                         break;
90                                 }
91                         }
92                         if (j == max_ext_count)
93                                 copy_count++;
94                 }
95                 vk_free(vk_get_allocator(NULL, NULL), device_extensions);
96
97                 *count = max_ext_count + copy_count;
98
99                 return VK_SUCCESS;
100         }
101
102         max_ext_count += ARRAY_LENGTH(wsi_device_extensions);
103
104         /* Copy ICD extensions and WSI extensions together into the given pointer. */
105
106         /* Calculate the number of extensions we have to copy. */
107         remaining = MIN(*count, max_ext_count);
108
109         /* Copy ICD extensions first. */
110         copied = remaining;
111         result = icd->enum_dev_exts(pdev, layer_name, &copied, extensions);
112         VK_CHECK(result == VK_SUCCESS || result == VK_INCOMPLETE, return VK_ERROR_OUT_OF_HOST_MEMORY,
113                          "vkEnumerateDeviceExtensionProperties() failed.\n");
114
115         /* Calculate remaining extensions to copy. */
116         remaining = MIN(remaining - copied, ARRAY_LENGTH(wsi_device_extensions));
117
118         /* Copy non duplicate entries */
119         for (i = 0; i < ARRAY_LENGTH(wsi_device_extensions); i++) {
120                 for (j = 0; j < copied; j++) {
121                         if (strcmp(extensions[j].extensionName,
122                                            wsi_device_extensions[i].extensionName) == 0) {
123                                 max_ext_count--;
124                                 break;
125                         }
126                 }
127                 if (j == copied) {
128                         if (copy_count < remaining) {
129                                 memcpy(extensions + copied + copy_count,
130                                            &wsi_device_extensions[i], sizeof(VkExtensionProperties));
131                                 copy_count++;
132                         } else {
133                                 break;
134                         }
135                 }
136         }
137         copied += copy_count;
138
139         /* Return the number of extensions copied. */
140         *count = copied;
141
142         if (*count < max_ext_count)
143                 return VK_INCOMPLETE;
144
145         return VK_SUCCESS;
146 }