1 // Copyright 2018 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "VkSurfaceKHR.hpp"
16
17 #include "Vulkan/VkDestroy.hpp"
18
19 #include <algorithm>
20
21 namespace {
22
23 static const VkSurfaceFormatKHR surfaceFormats[] = {
24 { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
25 { VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
26 };
27
28 static const VkPresentModeKHR presentModes[] = {
29 // FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
30 // with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
31 // should convert to using the Present extension, which allows us to request presentation
32 // at particular msc values. Will need a similar solution on Windows - possibly interact
33 // with DXGI directly.
34 VK_PRESENT_MODE_FIFO_KHR,
35 VK_PRESENT_MODE_MAILBOX_KHR,
36 };
37
38 } // namespace
39
40 namespace vk {
41
createImage(VkDevice device,const VkImageCreateInfo & createInfo)42 VkResult PresentImage::createImage(VkDevice device, const VkImageCreateInfo &createInfo)
43 {
44 VkImage image;
45 VkResult status = vkCreateImage(device, &createInfo, nullptr, &image);
46 if(status != VK_SUCCESS)
47 {
48 return status;
49 }
50
51 this->image = Cast(image);
52
53 return status;
54 }
55
allocateAndBindImageMemory(VkDevice device,const VkMemoryAllocateInfo & allocateInfo)56 VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
57 {
58 ASSERT(image);
59
60 VkDeviceMemory deviceMemory;
61 VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, &deviceMemory);
62 if(status != VK_SUCCESS)
63 {
64 return status;
65 }
66
67 imageMemory = Cast(deviceMemory);
68 vkBindImageMemory(device, *image, deviceMemory, 0);
69 imageStatus = AVAILABLE;
70
71 return VK_SUCCESS;
72 }
73
release()74 void PresentImage::release()
75 {
76 if(imageMemory)
77 {
78 vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
79 imageMemory = nullptr;
80 }
81
82 if(image)
83 {
84 vk::destroy(static_cast<VkImage>(*image), nullptr);
85 image = nullptr;
86 }
87
88 imageStatus = NONEXISTENT;
89 }
90
asVkImage() const91 VkImage PresentImage::asVkImage() const
92 {
93 return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
94 }
95
getSurfaceFormatsCount() const96 uint32_t SurfaceKHR::getSurfaceFormatsCount() const
97 {
98 return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
99 }
100
getSurfaceFormats(uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats) const101 VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
102 {
103 uint32_t count = getSurfaceFormatsCount();
104
105 uint32_t i;
106 for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
107 {
108 pSurfaceFormats[i] = surfaceFormats[i];
109 }
110
111 *pSurfaceFormatCount = i;
112
113 if(*pSurfaceFormatCount < count)
114 {
115 return VK_INCOMPLETE;
116 }
117
118 return VK_SUCCESS;
119 }
120
getPresentModeCount() const121 uint32_t SurfaceKHR::getPresentModeCount() const
122 {
123 return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
124 }
125
getPresentModes(uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes) const126 VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
127 {
128 uint32_t count = getPresentModeCount();
129
130 uint32_t i;
131 for(i = 0; i < std::min(*pPresentModeCount, count); i++)
132 {
133 pPresentModes[i] = presentModes[i];
134 }
135
136 *pPresentModeCount = i;
137
138 if(*pPresentModeCount < count)
139 {
140 return VK_INCOMPLETE;
141 }
142
143 return VK_SUCCESS;
144 }
145
associateSwapchain(SwapchainKHR * swapchain)146 void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
147 {
148 associatedSwapchain = swapchain;
149 }
150
disassociateSwapchain()151 void SurfaceKHR::disassociateSwapchain()
152 {
153 associatedSwapchain = nullptr;
154 }
155
hasAssociatedSwapchain()156 bool SurfaceKHR::hasAssociatedSwapchain()
157 {
158 return (associatedSwapchain != nullptr);
159 }
160
getPresentRectangles(uint32_t * pRectCount,VkRect2D * pRects) const161 VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
162 {
163 if(!pRects)
164 {
165 *pRectCount = 1;
166 return VK_SUCCESS;
167 }
168
169 if(*pRectCount < 1)
170 {
171 return VK_INCOMPLETE;
172 }
173
174 VkSurfaceCapabilitiesKHR capabilities;
175 getSurfaceCapabilities(&capabilities);
176
177 pRects[0].offset = { 0, 0 };
178 pRects[0].extent = capabilities.currentExtent;
179 *pRectCount = 1;
180
181 return VK_SUCCESS;
182 }
183
setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)184 void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
185 {
186 pSurfaceCapabilities->minImageCount = 1;
187 pSurfaceCapabilities->maxImageCount = 0;
188
189 pSurfaceCapabilities->maxImageArrayLayers = 1;
190
191 pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
192 pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
193 pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
194 pSurfaceCapabilities->supportedUsageFlags =
195 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
196 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
197 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
198 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
199 VK_IMAGE_USAGE_SAMPLED_BIT |
200 VK_IMAGE_USAGE_STORAGE_BIT;
201 }
202
203 } // namespace vk