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
allocateImage(VkDevice device,const VkImageCreateInfo & createInfo)42 VkResult PresentImage::allocateImage(VkDevice device, const VkImageCreateInfo &createInfo)
43 {
44 VkImage *vkImagePtr = reinterpret_cast<VkImage *>(allocate(sizeof(VkImage), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
45 if(!vkImagePtr)
46 {
47 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
48 }
49
50 VkResult status = vkCreateImage(device, &createInfo, nullptr, vkImagePtr);
51 if(status != VK_SUCCESS)
52 {
53 deallocate(vkImagePtr, DEVICE_MEMORY);
54 return status;
55 }
56
57 image = Cast(*vkImagePtr);
58 deallocate(vkImagePtr, DEVICE_MEMORY);
59
60 return status;
61 }
62
allocateAndBindImageMemory(VkDevice device,const VkMemoryAllocateInfo & allocateInfo)63 VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
64 {
65 ASSERT(image);
66
67 VkDeviceMemory *vkDeviceMemoryPtr = reinterpret_cast<VkDeviceMemory *>(
68 allocate(sizeof(VkDeviceMemory), REQUIRED_MEMORY_ALIGNMENT, DEVICE_MEMORY));
69 if(!vkDeviceMemoryPtr)
70 {
71 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
72 }
73
74 VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, vkDeviceMemoryPtr);
75 if(status != VK_SUCCESS)
76 {
77 deallocate(vkDeviceMemoryPtr, DEVICE_MEMORY);
78 return status;
79 }
80
81 imageMemory = Cast(*vkDeviceMemoryPtr);
82 vkBindImageMemory(device, *image, *vkDeviceMemoryPtr, 0);
83
84 imageStatus = AVAILABLE;
85 deallocate(vkDeviceMemoryPtr, DEVICE_MEMORY);
86
87 return status;
88 }
89
clear()90 void PresentImage::clear()
91 {
92 if(imageMemory)
93 {
94 vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
95 imageMemory = nullptr;
96 }
97
98 if(image)
99 {
100 vk::destroy(static_cast<VkImage>(*image), nullptr);
101 image = nullptr;
102 }
103
104 imageStatus = NONEXISTENT;
105 }
106
asVkImage() const107 VkImage PresentImage::asVkImage() const
108 {
109 return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
110 }
111
getSurfaceFormatsCount() const112 uint32_t SurfaceKHR::getSurfaceFormatsCount() const
113 {
114 return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
115 }
116
getSurfaceFormats(uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats) const117 VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
118 {
119 uint32_t count = getSurfaceFormatsCount();
120
121 uint32_t i;
122 for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
123 {
124 pSurfaceFormats[i] = surfaceFormats[i];
125 }
126
127 *pSurfaceFormatCount = i;
128
129 if(*pSurfaceFormatCount < count)
130 {
131 return VK_INCOMPLETE;
132 }
133
134 return VK_SUCCESS;
135 }
136
getPresentModeCount() const137 uint32_t SurfaceKHR::getPresentModeCount() const
138 {
139 return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
140 }
141
getPresentModes(uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes) const142 VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
143 {
144 uint32_t count = getPresentModeCount();
145
146 uint32_t i;
147 for(i = 0; i < std::min(*pPresentModeCount, count); i++)
148 {
149 pPresentModes[i] = presentModes[i];
150 }
151
152 *pPresentModeCount = i;
153
154 if(*pPresentModeCount < count)
155 {
156 return VK_INCOMPLETE;
157 }
158
159 return VK_SUCCESS;
160 }
161
associateSwapchain(SwapchainKHR * swapchain)162 void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
163 {
164 associatedSwapchain = swapchain;
165 }
166
disassociateSwapchain()167 void SurfaceKHR::disassociateSwapchain()
168 {
169 associatedSwapchain = nullptr;
170 }
171
hasAssociatedSwapchain()172 bool SurfaceKHR::hasAssociatedSwapchain()
173 {
174 return (associatedSwapchain != nullptr);
175 }
176
getPresentRectangles(uint32_t * pRectCount,VkRect2D * pRects) const177 VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
178 {
179 if(!pRects)
180 {
181 *pRectCount = 1;
182 return VK_SUCCESS;
183 }
184
185 if(*pRectCount < 1)
186 {
187 return VK_INCOMPLETE;
188 }
189
190 VkSurfaceCapabilitiesKHR capabilities;
191 getSurfaceCapabilities(&capabilities);
192
193 pRects[0].offset = { 0, 0 };
194 pRects[0].extent = capabilities.currentExtent;
195 *pRectCount = 1;
196
197 return VK_SUCCESS;
198 }
199
setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)200 void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
201 {
202 pSurfaceCapabilities->minImageCount = 1;
203 pSurfaceCapabilities->maxImageCount = 0;
204
205 pSurfaceCapabilities->maxImageArrayLayers = 1;
206
207 pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
208 pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
209 pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
210 pSurfaceCapabilities->supportedUsageFlags =
211 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
212 VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
213 VK_IMAGE_USAGE_TRANSFER_DST_BIT |
214 VK_IMAGE_USAGE_SAMPLED_BIT;
215 }
216
217 } // namespace vk