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