layer: improve how layer handles Vulkan extensions
[platform/core/uifw/vulkan-wsi-tizen.git] / layer / swapchain_api.cpp
1 /*
2  * Copyright (c) 2017, 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 /**
26  * @file swapchain_api.cpp
27  *
28  * @brief Contains the Vulkan entrypoints for the swapchain.
29  */
30
31 #include <cassert>
32 #include <cstdlib>
33 #include <new>
34
35 #include <wsi/wsi_factory.hpp>
36
37 #include "private_data.hpp"
38 #include "swapchain_api.hpp"
39
40 extern "C" {
41
42 VKAPI_ATTR VkResult wsi_layer_vkCreateSwapchainKHR(VkDevice device,
43                                                    const VkSwapchainCreateInfoKHR *pSwapchainCreateInfo,
44                                                    const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain)
45 {
46    assert(pSwapchain != nullptr);
47    layer::device_private_data &device_data = layer::device_private_data::get(device);
48    VkSurfaceKHR surface = pSwapchainCreateInfo->surface;
49
50    if (!device_data.should_layer_create_swapchain(surface))
51    {
52       if (!device_data.can_icds_create_swapchain(surface))
53       {
54          return VK_ERROR_INITIALIZATION_FAILED;
55       }
56       return device_data.disp.CreateSwapchainKHR(device_data.device, pSwapchainCreateInfo, pAllocator, pSwapchain);
57    }
58
59    wsi::swapchain_base *sc = wsi::allocate_surface_swapchain(surface, device_data, pAllocator);
60    if (sc == nullptr)
61    {
62       return VK_ERROR_OUT_OF_HOST_MEMORY;
63    }
64
65    VkResult result = sc->init(device, pSwapchainCreateInfo);
66    if (result != VK_SUCCESS)
67    {
68       /* Error occured during initialization, need to free allocated memory. */
69       wsi::destroy_surface_swapchain(sc, pAllocator);
70       return result;
71    }
72
73    *pSwapchain = reinterpret_cast<VkSwapchainKHR>(sc);
74    device_data.add_layer_swapchain(*pSwapchain);
75    return result;
76 }
77
78 VKAPI_ATTR void wsi_layer_vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapc,
79                                                 const VkAllocationCallbacks *pAllocator)
80 {
81    layer::device_private_data &device_data = layer::device_private_data::get(device);
82
83    if (!device_data.layer_owns_swapchain(swapc))
84    {
85       return device_data.disp.DestroySwapchainKHR(device_data.device, swapc, pAllocator);
86    }
87
88    assert(swapc != VK_NULL_HANDLE);
89    wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
90    wsi::destroy_surface_swapchain(sc, pAllocator);
91 }
92
93 VKAPI_ATTR VkResult wsi_layer_vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapc,
94                                                       uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages)
95 {
96    layer::device_private_data &device_data = layer::device_private_data::get(device);
97
98    if (!device_data.layer_owns_swapchain(swapc))
99    {
100       return device_data.disp.GetSwapchainImagesKHR(device_data.device, swapc, pSwapchainImageCount, pSwapchainImages);
101    }
102
103    assert(pSwapchainImageCount != nullptr);
104    assert(swapc != VK_NULL_HANDLE);
105    wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
106    return sc->get_swapchain_images(pSwapchainImageCount, pSwapchainImages);
107 }
108
109 VKAPI_ATTR VkResult wsi_layer_vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapc, uint64_t timeout,
110                                                     VkSemaphore semaphore, VkFence fence, uint32_t *pImageIndex)
111 {
112    layer::device_private_data &device_data = layer::device_private_data::get(device);
113
114    if (!device_data.layer_owns_swapchain(swapc))
115    {
116       return device_data.disp.AcquireNextImageKHR(device_data.device, swapc, timeout, semaphore, fence, pImageIndex);
117    }
118
119    assert(swapc != VK_NULL_HANDLE);
120    assert(semaphore != VK_NULL_HANDLE || fence != VK_NULL_HANDLE);
121    assert(pImageIndex != nullptr);
122    wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
123    return sc->acquire_next_image(timeout, semaphore, fence, pImageIndex);
124 }
125
126 VKAPI_ATTR VkResult wsi_layer_vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR *pPresentInfo)
127 {
128    assert(queue != VK_NULL_HANDLE);
129    assert(pPresentInfo != nullptr);
130
131    layer::device_private_data &device_data = layer::device_private_data::get(queue);
132
133    if (!device_data.layer_owns_all_swapchains(pPresentInfo->pSwapchains, pPresentInfo->swapchainCount))
134    {
135       return device_data.disp.QueuePresentKHR(queue, pPresentInfo);
136    }
137
138    VkResult ret = VK_SUCCESS;
139    for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i)
140    {
141       VkSwapchainKHR swapc = pPresentInfo->pSwapchains[i];
142
143       wsi::swapchain_base *sc = reinterpret_cast<wsi::swapchain_base *>(swapc);
144       assert(sc != nullptr);
145
146       VkResult res = sc->queue_present(queue, pPresentInfo, pPresentInfo->pImageIndices[i]);
147
148       if (pPresentInfo->pResults != nullptr)
149       {
150          pPresentInfo->pResults[i] = res;
151       }
152
153       if (res != VK_SUCCESS && ret == VK_SUCCESS)
154       {
155          ret = res;
156       }
157    }
158
159    return ret;
160 }
161
162 } /* extern "C" */