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 release();
65 return status;
66 }
67
68 imageMemory = Cast(deviceMemory);
69 vkBindImageMemory(device, *image, deviceMemory, 0);
70 imageStatus = AVAILABLE;
71
72 return VK_SUCCESS;
73 }
74
release()75 void PresentImage::release()
76 {
77 if(imageMemory)
78 {
79 vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
80 imageMemory = nullptr;
81 }
82
83 if(image)
84 {
85 vk::destroy(static_cast<VkImage>(*image), nullptr);
86 image = nullptr;
87 }
88
89 imageStatus = NONEXISTENT;
90 }
91
asVkImage() const92 VkImage PresentImage::asVkImage() const
93 {
94 return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
95 }
96
getSurfaceFormatsCount() const97 uint32_t SurfaceKHR::getSurfaceFormatsCount() const
98 {
99 return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
100 }
101
getSurfaceFormats(uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats) const102 VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
103 {
104 uint32_t count = getSurfaceFormatsCount();
105
106 uint32_t i;
107 for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
108 {
109 pSurfaceFormats[i] = surfaceFormats[i];
110 }
111
112 *pSurfaceFormatCount = i;
113
114 if(*pSurfaceFormatCount < count)
115 {
116 return VK_INCOMPLETE;
117 }
118
119 return VK_SUCCESS;
120 }
121
getPresentModeCount() const122 uint32_t SurfaceKHR::getPresentModeCount() const
123 {
124 return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
125 }
126
getPresentModes(uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes) const127 VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
128 {
129 uint32_t count = getPresentModeCount();
130
131 uint32_t i;
132 for(i = 0; i < std::min(*pPresentModeCount, count); i++)
133 {
134 pPresentModes[i] = presentModes[i];
135 }
136
137 *pPresentModeCount = i;
138
139 if(*pPresentModeCount < count)
140 {
141 return VK_INCOMPLETE;
142 }
143
144 return VK_SUCCESS;
145 }
146
associateSwapchain(SwapchainKHR * swapchain)147 void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
148 {
149 associatedSwapchain = swapchain;
150 }
151
disassociateSwapchain()152 void SurfaceKHR::disassociateSwapchain()
153 {
154 associatedSwapchain = nullptr;
155 }
156
hasAssociatedSwapchain()157 bool SurfaceKHR::hasAssociatedSwapchain()
158 {
159 return (associatedSwapchain != nullptr);
160 }
161
getPresentRectangles(uint32_t * pRectCount,VkRect2D * pRects) const162 VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
163 {
164 if(!pRects)
165 {
166 *pRectCount = 1;
167 return VK_SUCCESS;
168 }
169
170 if(*pRectCount < 1)
171 {
172 return VK_INCOMPLETE;
173 }
174
175 VkSurfaceCapabilitiesKHR capabilities;
176 getSurfaceCapabilities(&capabilities);
177
178 pRects[0].offset = { 0, 0 };
179 pRects[0].extent = capabilities.currentExtent;
180 *pRectCount = 1;
181
182 return VK_SUCCESS;
183 }
184
setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)185 void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
186 {
187 pSurfaceCapabilities->minImageCount = 1;
188 pSurfaceCapabilities->maxImageCount = 0;
189
190 pSurfaceCapabilities->maxImageArrayLayers = 1;
191
192 pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
193 pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
194 pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
195 pSurfaceCapabilities->supportedUsageFlags =
196 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
197 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
198 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
199 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
200 VK_IMAGE_USAGE_SAMPLED_BIT |
201 VK_IMAGE_USAGE_STORAGE_BIT;
202 }
203
204 } // namespace vk