1 // Copyright 2019 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 "Win32SurfaceKHR.hpp"
16
17 #include "System/Debug.hpp"
18 #include "Vulkan/VkDeviceMemory.hpp"
19
20 #include <string.h>
21
22 namespace {
getWindowSize(HWND hwnd,VkExtent2D & windowSize)23 VkResult getWindowSize(HWND hwnd, VkExtent2D &windowSize)
24 {
25 RECT clientRect = {};
26 if(!IsWindow(hwnd) || !GetClientRect(hwnd, &clientRect))
27 {
28 windowSize = { 0, 0 };
29 return VK_ERROR_SURFACE_LOST_KHR;
30 }
31
32 windowSize = { static_cast<uint32_t>(clientRect.right - clientRect.left),
33 static_cast<uint32_t>(clientRect.bottom - clientRect.top) };
34
35 return VK_SUCCESS;
36 }
37 } // namespace
38
39 namespace vk {
40
Win32SurfaceKHR(const VkWin32SurfaceCreateInfoKHR * pCreateInfo,void * mem)41 Win32SurfaceKHR::Win32SurfaceKHR(const VkWin32SurfaceCreateInfoKHR *pCreateInfo, void *mem)
42 : hwnd(pCreateInfo->hwnd)
43 {
44 ASSERT(IsWindow(hwnd) == TRUE);
45 windowContext = GetDC(hwnd);
46 }
47
destroySurface(const VkAllocationCallbacks * pAllocator)48 void Win32SurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
49 {
50 ReleaseDC(hwnd, windowContext);
51 }
52
ComputeRequiredAllocationSize(const VkWin32SurfaceCreateInfoKHR * pCreateInfo)53 size_t Win32SurfaceKHR::ComputeRequiredAllocationSize(const VkWin32SurfaceCreateInfoKHR *pCreateInfo)
54 {
55 return 0;
56 }
57
getSurfaceCapabilities(const void * pSurfaceInfoPNext,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities,void * pSurfaceCapabilitiesPNext) const58 VkResult Win32SurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const
59 {
60 VkExtent2D extent;
61 VkResult result = getWindowSize(hwnd, extent);
62 pSurfaceCapabilities->currentExtent = extent;
63 pSurfaceCapabilities->minImageExtent = extent;
64 pSurfaceCapabilities->maxImageExtent = extent;
65
66 setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext);
67 return VK_SUCCESS;
68 }
69
attachImage(PresentImage * image)70 void Win32SurfaceKHR::attachImage(PresentImage *image)
71 {
72 // Nothing to do here, the current implementation based on GDI blits on
73 // present instead of associating the image with the surface.
74 }
75
detachImage(PresentImage * image)76 void Win32SurfaceKHR::detachImage(PresentImage *image)
77 {
78 // Nothing to do here, the current implementation based on GDI blits on
79 // present instead of associating the image with the surface.
80 }
81
present(PresentImage * image)82 VkResult Win32SurfaceKHR::present(PresentImage *image)
83 {
84 VkExtent2D windowExtent = {};
85 VkResult result = getWindowSize(hwnd, windowExtent);
86 if(result != VK_SUCCESS)
87 {
88 return result;
89 }
90
91 const Image *vkImage = image->getImage();
92 const VkExtent3D &extent = vkImage->getExtent();
93 if(windowExtent.width != extent.width || windowExtent.height != extent.height)
94 {
95 return VK_ERROR_OUT_OF_DATE_KHR;
96 }
97
98 int stride = vkImage->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
99 int bytesPerPixel = static_cast<int>(vkImage->getFormat(VK_IMAGE_ASPECT_COLOR_BIT).bytes());
100
101 BITMAPINFO bitmapInfo = {};
102 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO);
103 bitmapInfo.bmiHeader.biBitCount = bytesPerPixel * 8;
104 bitmapInfo.bmiHeader.biPlanes = 1;
105 bitmapInfo.bmiHeader.biHeight = -static_cast<LONG>(extent.height); // Negative for top-down DIB, origin in upper-left corner
106 bitmapInfo.bmiHeader.biWidth = stride / bytesPerPixel;
107 bitmapInfo.bmiHeader.biCompression = BI_RGB;
108
109 void *bits = image->getImage()->getTexelPointer({ 0, 0, 0 }, { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 });
110 StretchDIBits(windowContext, 0, 0, extent.width, extent.height, 0, 0, extent.width, extent.height, bits, &bitmapInfo, DIB_RGB_COLORS, SRCCOPY);
111
112 return VK_SUCCESS;
113 }
114
115 } // namespace vk
116