layer: improve how layer handles Vulkan extensions
[platform/core/uifw/vulkan-wsi-tizen.git] / util / extension_list.cpp
1 /*
2  * Copyright (c) 2019, 2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the 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 THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #include "extension_list.hpp"
26 #include <layer/private_data.hpp>
27 #include <string.h>
28 #include <cassert>
29
30 namespace util
31 {
32
33 extension_list::extension_list(const util::allocator& allocator)
34    : m_alloc{allocator}
35    , m_ext_props(allocator)
36 {
37 }
38
39 VkResult extension_list::add(const struct VkEnumerateInstanceExtensionPropertiesChain *chain)
40 {
41    uint32_t count;
42    VkResult m_error = chain->CallDown(nullptr, &count, nullptr);
43    if (m_error == VK_SUCCESS)
44    {
45       if (!m_ext_props.try_resize(count))
46       {
47          return VK_ERROR_OUT_OF_HOST_MEMORY;
48       }
49       m_error = chain->CallDown(nullptr, &count, m_ext_props.data());
50    }
51    return m_error;
52 }
53
54 VkResult extension_list::add(VkPhysicalDevice dev)
55 {
56    layer::instance_private_data &inst_data = layer::instance_private_data::get(dev);
57    uint32_t count;
58    VkResult m_error = inst_data.disp.EnumerateDeviceExtensionProperties(dev, nullptr, &count, nullptr);
59
60    if (m_error == VK_SUCCESS)
61    {
62       if (!m_ext_props.try_resize(count))
63       {
64          return VK_ERROR_OUT_OF_HOST_MEMORY;
65       }
66       m_error = inst_data.disp.EnumerateDeviceExtensionProperties(dev, nullptr, &count, m_ext_props.data());
67    }
68    return m_error;
69 }
70
71 VkResult extension_list::add(PFN_vkEnumerateInstanceExtensionProperties fpEnumerateInstanceExtensionProperties)
72 {
73    uint32_t count = 0;
74    VkResult m_error = fpEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
75
76    if (m_error == VK_SUCCESS)
77    {
78       if (!m_ext_props.try_resize(count))
79       {
80          return VK_ERROR_OUT_OF_HOST_MEMORY;
81       }
82       m_error = fpEnumerateInstanceExtensionProperties(nullptr, &count, m_ext_props.data());
83    }
84    return m_error;
85 }
86
87 VkResult extension_list::add(const char *const *extensions, uint32_t count)
88 {
89    for (uint32_t i = 0; i < count; i++)
90    {
91       VkExtensionProperties props = {};
92       strncpy(props.extensionName, extensions[i], sizeof(props.extensionName));
93       if (!m_ext_props.try_push_back(props))
94       {
95          return VK_ERROR_OUT_OF_HOST_MEMORY;
96       }
97    }
98    return VK_SUCCESS;
99 }
100
101 VkResult extension_list::add(const VkExtensionProperties *props, uint32_t count)
102 {
103    if (!m_ext_props.try_push_back_many(props, props + count))
104    {
105       return VK_ERROR_OUT_OF_HOST_MEMORY;
106    }
107    return VK_SUCCESS;
108 }
109
110 VkResult extension_list::add(const char *ext)
111 {
112    if (!contains(ext))
113    {
114       VkExtensionProperties props = {};
115       strncpy(props.extensionName, ext, sizeof(props.extensionName));
116       if (!m_ext_props.try_push_back(props))
117       {
118          return VK_ERROR_OUT_OF_HOST_MEMORY;
119       }
120    }
121    return VK_SUCCESS;
122 }
123
124 VkResult extension_list::add(VkExtensionProperties ext_prop)
125 {
126    if (!contains(ext_prop.extensionName))
127    {
128       if (!m_ext_props.try_push_back(ext_prop))
129       {
130          return VK_ERROR_OUT_OF_HOST_MEMORY;
131       }
132    }
133    return VK_SUCCESS;
134 }
135
136 VkResult extension_list::add(const char **ext_list, uint32_t count)
137 {
138    for (uint32_t i = 0; i < count; i++)
139    {
140       if (add(ext_list[i]) != VK_SUCCESS)
141       {
142          return VK_ERROR_OUT_OF_HOST_MEMORY;
143       }
144    }
145    return VK_SUCCESS;
146 }
147
148 VkResult extension_list::add(const extension_list &ext_list)
149 {
150    util::vector<VkExtensionProperties> ext_vect = ext_list.get_extension_props();
151    for (auto &ext : ext_vect)
152    {
153       if (add(ext) != VK_SUCCESS)
154       {
155          return VK_ERROR_OUT_OF_HOST_MEMORY;
156       }
157    }
158    return VK_SUCCESS;
159 }
160
161 bool extension_list::get_extension_strings(util::vector<const char*> &out) const
162 {
163    size_t old_size = out.size();
164    size_t new_size = old_size + m_ext_props.size();
165    if (!out.try_resize(new_size))
166    {
167       return false;
168    }
169
170    for (size_t i = old_size; i < new_size; i++)
171    {
172       out[i] = m_ext_props[i - old_size].extensionName;
173    }
174    return true;
175 }
176
177 bool extension_list::contains(const extension_list &req) const
178 {
179    for (const auto &req_ext : req.m_ext_props)
180    {
181       if (!contains(req_ext.extensionName))
182       {
183          return false;
184       }
185    }
186    return true;
187 }
188
189 bool extension_list::contains(const char *extension_name) const
190 {
191    for (const auto &p : m_ext_props)
192    {
193       if (strcmp(p.extensionName, extension_name) == 0)
194       {
195          return true;
196       }
197    }
198    return false;
199 }
200
201 void extension_list::remove(const char *ext)
202 {
203    m_ext_props.erase(std::remove_if(m_ext_props.begin(), m_ext_props.end(), [&ext](VkExtensionProperties ext_prop) {
204       return (strcmp(ext_prop.extensionName, ext) == 0);
205    }));
206 }
207 } // namespace util