xref: /aosp_15_r20/external/swiftshader/src/WSI/VkSurfaceKHR.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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 #include "Vulkan/VkStringify.hpp"
19 
20 #include <algorithm>
21 
22 namespace {
23 
24 static const VkSurfaceFormatKHR surfaceFormats[] = {
25 	{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
26 	{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
27 };
28 
29 static const VkPresentModeKHR presentModes[] = {
30 	// FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
31 	// with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
32 	// should convert to using the Present extension, which allows us to request presentation
33 	// at particular msc values. Will need a similar solution on Windows - possibly interact
34 	// with DXGI directly.
35 	VK_PRESENT_MODE_FIFO_KHR,
36 	VK_PRESENT_MODE_MAILBOX_KHR,
37 };
38 
39 }  // namespace
40 
41 namespace vk {
42 
createImage(VkDevice device,const VkImageCreateInfo & createInfo)43 VkResult PresentImage::createImage(VkDevice device, const VkImageCreateInfo &createInfo)
44 {
45 	VkImage image;
46 	VkResult status = vkCreateImage(device, &createInfo, nullptr, &image);
47 	if(status != VK_SUCCESS)
48 	{
49 		return status;
50 	}
51 
52 	this->image = Cast(image);
53 
54 	return status;
55 }
56 
allocateAndBindImageMemory(VkDevice device,const VkMemoryAllocateInfo & allocateInfo)57 VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
58 {
59 	ASSERT(image);
60 
61 	VkDeviceMemory deviceMemory;
62 	VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, &deviceMemory);
63 	if(status != VK_SUCCESS)
64 	{
65 		release();
66 		return status;
67 	}
68 
69 	imageMemory = Cast(deviceMemory);
70 	vkBindImageMemory(device, *image, deviceMemory, 0);
71 	imageStatus = AVAILABLE;
72 
73 	return VK_SUCCESS;
74 }
75 
release()76 void PresentImage::release()
77 {
78 	if(imageMemory)
79 	{
80 		vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
81 		imageMemory = nullptr;
82 	}
83 
84 	if(image)
85 	{
86 		vk::destroy(static_cast<VkImage>(*image), nullptr);
87 		image = nullptr;
88 	}
89 
90 	imageStatus = NONEXISTENT;
91 }
92 
asVkImage() const93 VkImage PresentImage::asVkImage() const
94 {
95 	return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
96 }
97 
getSurfaceFormatsCount(const void * pSurfaceInfoPNext) const98 uint32_t SurfaceKHR::getSurfaceFormatsCount(const void *pSurfaceInfoPNext) const
99 {
100 	return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
101 }
102 
getSurfaceFormats(const void * pSurfaceInfoPNext,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats) const103 VkResult SurfaceKHR::getSurfaceFormats(const void *pSurfaceInfoPNext, uint32_t *pSurfaceFormatCount, VkSurfaceFormat2KHR *pSurfaceFormats) const
104 {
105 	uint32_t count = getSurfaceFormatsCount(pSurfaceInfoPNext);
106 
107 	uint32_t i;
108 	for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
109 	{
110 		pSurfaceFormats[i].surfaceFormat = surfaceFormats[i];
111 	}
112 
113 	*pSurfaceFormatCount = i;
114 
115 	if(*pSurfaceFormatCount < count)
116 	{
117 		return VK_INCOMPLETE;
118 	}
119 
120 	return VK_SUCCESS;
121 }
122 
getPresentModeCount() const123 uint32_t SurfaceKHR::getPresentModeCount() const
124 {
125 	return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
126 }
127 
getPresentModes(uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes) const128 VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
129 {
130 	uint32_t count = getPresentModeCount();
131 
132 	uint32_t i;
133 	for(i = 0; i < std::min(*pPresentModeCount, count); i++)
134 	{
135 		pPresentModes[i] = presentModes[i];
136 	}
137 
138 	*pPresentModeCount = i;
139 
140 	if(*pPresentModeCount < count)
141 	{
142 		return VK_INCOMPLETE;
143 	}
144 
145 	return VK_SUCCESS;
146 }
147 
associateSwapchain(SwapchainKHR * swapchain)148 void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
149 {
150 	associatedSwapchain = swapchain;
151 }
152 
disassociateSwapchain()153 void SurfaceKHR::disassociateSwapchain()
154 {
155 	associatedSwapchain = nullptr;
156 }
157 
hasAssociatedSwapchain()158 bool SurfaceKHR::hasAssociatedSwapchain()
159 {
160 	return (associatedSwapchain != nullptr);
161 }
162 
getPresentRectangles(uint32_t * pRectCount,VkRect2D * pRects) const163 VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
164 {
165 	if(!pRects)
166 	{
167 		*pRectCount = 1;
168 		return VK_SUCCESS;
169 	}
170 
171 	if(*pRectCount < 1)
172 	{
173 		return VK_INCOMPLETE;
174 	}
175 
176 	VkSurfaceCapabilitiesKHR capabilities;
177 	getSurfaceCapabilities(nullptr, &capabilities, nullptr);
178 
179 	pRects[0].offset = { 0, 0 };
180 	pRects[0].extent = capabilities.currentExtent;
181 	*pRectCount = 1;
182 
183 	return VK_SUCCESS;
184 }
185 
setCommonSurfaceCapabilities(const void * pSurfaceInfoPNext,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities,void * pSurfaceCapabilitiesPNext)186 void SurfaceKHR::setCommonSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext)
187 {
188 	pSurfaceCapabilities->minImageCount = 1;
189 	pSurfaceCapabilities->maxImageCount = 0;
190 
191 	pSurfaceCapabilities->maxImageArrayLayers = 1;
192 
193 	pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
194 	pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
195 	pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
196 	pSurfaceCapabilities->supportedUsageFlags =
197 	    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
198 	    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
199 	    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
200 	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
201 	    VK_IMAGE_USAGE_SAMPLED_BIT |
202 	    VK_IMAGE_USAGE_STORAGE_BIT;
203 
204 	auto *extInfo = reinterpret_cast<VkBaseOutStructure *>(pSurfaceCapabilitiesPNext);
205 	while(extInfo)
206 	{
207 		switch(extInfo->sType)
208 		{
209 		case VK_STRUCTURE_TYPE_SURFACE_PRESENT_SCALING_CAPABILITIES_EXT:
210 			{
211 				// Supported scaling is per present mode, but currently that's identical for all present modes.
212 				ASSERT(vk::GetExtendedStruct<VkSurfacePresentModeEXT>(pSurfaceInfoPNext, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT) != nullptr);
213 				VkSurfacePresentScalingCapabilitiesEXT *presentScalingCapabilities = reinterpret_cast<VkSurfacePresentScalingCapabilitiesEXT *>(extInfo);
214 				presentScalingCapabilities->supportedPresentScaling = 0;
215 				presentScalingCapabilities->supportedPresentGravityX = 0;
216 				presentScalingCapabilities->supportedPresentGravityY = 0;
217 				presentScalingCapabilities->minScaledImageExtent = pSurfaceCapabilities->minImageExtent;
218 				presentScalingCapabilities->maxScaledImageExtent = pSurfaceCapabilities->maxImageExtent;
219 				break;
220 			}
221 		case VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_COMPATIBILITY_EXT:
222 			{
223 				VkSurfacePresentModeCompatibilityEXT *presentModeCompatibility = reinterpret_cast<VkSurfacePresentModeCompatibilityEXT *>(extInfo);
224 				const auto *presentMode = vk::GetExtendedStruct<VkSurfacePresentModeEXT>(pSurfaceInfoPNext, VK_STRUCTURE_TYPE_SURFACE_PRESENT_MODE_EXT);
225 				ASSERT(presentMode != nullptr);
226 
227 				// Present mode is ignored, so FIFO and MAILBOX are compatible.
228 				if(presentModeCompatibility->pPresentModes == nullptr)
229 				{
230 					presentModeCompatibility->presentModeCount = 2;
231 				}
232 				else if(presentModeCompatibility->presentModeCount == 1)
233 				{
234 					presentModeCompatibility->pPresentModes[0] = presentMode->presentMode;
235 					presentModeCompatibility->presentModeCount = 1;
236 				}
237 				else if(presentModeCompatibility->presentModeCount > 1)
238 				{
239 					presentModeCompatibility->pPresentModes[0] = presentModes[0];
240 					presentModeCompatibility->pPresentModes[1] = presentModes[1];
241 					presentModeCompatibility->presentModeCount = 2;
242 				}
243 				break;
244 			}
245 		default:
246 			UNSUPPORTED("pSurfaceCapabilities->pNext sType = %s", vk::Stringify(extInfo->sType).c_str());
247 			break;
248 		}
249 		extInfo = extInfo->pNext;
250 	}
251 }
252 
253 }  // namespace vk
254