blob: 27ab614c8784f109543317a88054806c3b5dff8d [file] [log] [blame]
Nicolas Capensd3545372019-08-09 13:59:18 -04001// 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 "Vulkan/VkDeviceMemory.hpp"
18#include "Vulkan/VkDebug.hpp"
19
Nicolas Capensd3545372019-08-09 13:59:18 -040020#include <string.h>
21
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040022namespace
23{
24 VkExtent2D getWindowSize(HWND hwnd)
25 {
26 RECT clientRect = {};
27 BOOL status = GetClientRect(hwnd, &clientRect);
28 ASSERT(status != 0);
29
30 int windowWidth = clientRect.right - clientRect.left;
31 int windowHeight = clientRect.bottom - clientRect.top;
32
33 return { static_cast<uint32_t>(windowWidth), static_cast<uint32_t>(windowHeight) };
34 }
35}
36
Nicolas Capensd3545372019-08-09 13:59:18 -040037namespace vk {
38
39Win32SurfaceKHR::Win32SurfaceKHR(const VkWin32SurfaceCreateInfoKHR *pCreateInfo, void *mem) :
Nicolas Capensd3545372019-08-09 13:59:18 -040040 hwnd(pCreateInfo->hwnd)
41{
42 ASSERT(IsWindow(hwnd) == TRUE);
Nicolas Capensd3545372019-08-09 13:59:18 -040043 windowContext = GetDC(hwnd);
44 bitmapContext = CreateCompatibleDC(windowContext);
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040045 lazyCreateFrameBuffer();
Nicolas Capensd3545372019-08-09 13:59:18 -040046}
47
48void Win32SurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
49{
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040050 destroyFrameBuffer();
Nicolas Capensd3545372019-08-09 13:59:18 -040051 ReleaseDC(hwnd, windowContext);
52 DeleteDC(bitmapContext);
53}
54
55size_t Win32SurfaceKHR::ComputeRequiredAllocationSize(const VkWin32SurfaceCreateInfoKHR *pCreateInfo)
56{
57 return 0;
58}
59
60void Win32SurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
61{
62 SurfaceKHR::getSurfaceCapabilities(pSurfaceCapabilities);
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040063 VkExtent2D extent = getWindowSize(hwnd);
Nicolas Capensd3545372019-08-09 13:59:18 -040064 pSurfaceCapabilities->currentExtent = extent;
65 pSurfaceCapabilities->minImageExtent = extent;
66 pSurfaceCapabilities->maxImageExtent = extent;
67}
68
69void Win32SurfaceKHR::attachImage(PresentImage* image)
70{
71 // Nothing to do here, the current implementation based on GDI blits on
72 // present instead of associating the image with the surface.
73}
74
75void Win32SurfaceKHR::detachImage(PresentImage* image)
76{
77 // Nothing to do here, the current implementation based on GDI blits on
78 // present instead of associating the image with the surface.
79}
80
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040081VkResult Win32SurfaceKHR::present(PresentImage* image)
Nicolas Capensd3545372019-08-09 13:59:18 -040082{
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040083 // Recreate frame buffer in case window size has changed
84 lazyCreateFrameBuffer();
85
Nicolas Capensd3545372019-08-09 13:59:18 -040086 if(!framebuffer)
87 {
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040088 // e.g. window width or height is 0
89 return VK_SUCCESS;
Nicolas Capensd3545372019-08-09 13:59:18 -040090 }
91
92 VkExtent3D extent = image->getImage()->getMipLevelExtent(VK_IMAGE_ASPECT_COLOR_BIT, 0);
93
Nicolas Capens81bc9d92019-12-16 15:05:57 -050094 if(windowExtent.width != extent.width || windowExtent.height != extent.height)
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -040095 {
96 return VK_ERROR_OUT_OF_DATE_KHR;
97 }
98
99 VkImageSubresourceLayers subresourceLayers{};
100 subresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
101 subresourceLayers.layerCount = 1;
102
103 image->getImage()->blitToBuffer(subresourceLayers, VkOffset3D{}, extent, reinterpret_cast<uint8_t*>(framebuffer), bitmapRowPitch, 0);
Nicolas Capensd3545372019-08-09 13:59:18 -0400104
105 StretchBlt(windowContext, 0, 0, extent.width, extent.height, bitmapContext, 0, 0, extent.width, extent.height, SRCCOPY);
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400106
107 return VK_SUCCESS;
108}
109
110void Win32SurfaceKHR::lazyCreateFrameBuffer()
111{
112 auto currWindowExtent = getWindowSize(hwnd);
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500113 if(currWindowExtent.width == windowExtent.width && currWindowExtent.height == windowExtent.height)
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400114 {
115 return;
116 }
117
118 windowExtent = currWindowExtent;
119
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500120 if(framebuffer)
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400121 {
122 destroyFrameBuffer();
123 }
124
Nicolas Capens81bc9d92019-12-16 15:05:57 -0500125 if(windowExtent.width == 0 || windowExtent.height == 0)
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400126 {
127 return;
128 }
129
130 BITMAPINFO bitmapInfo = {};
131 bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO);
132 bitmapInfo.bmiHeader.biBitCount = 32;
133 bitmapInfo.bmiHeader.biPlanes = 1;
Antonio Maiorano992bf9d2019-10-22 09:41:17 -0400134 bitmapInfo.bmiHeader.biHeight = -static_cast<LONG>(windowExtent.height); // Negative for top-down DIB, origin in upper-left corner
Antonio Maiorano26c6c4a2019-10-17 15:33:47 -0400135 bitmapInfo.bmiHeader.biWidth = windowExtent.width;
136 bitmapInfo.bmiHeader.biCompression = BI_RGB;
137
138 bitmap = CreateDIBSection(bitmapContext, &bitmapInfo, DIB_RGB_COLORS, &framebuffer, 0, 0);
139 ASSERT(bitmap != NULL);
140 SelectObject(bitmapContext, bitmap);
141
142 BITMAP header;
143 int status = GetObject(bitmap, sizeof(BITMAP), &header);
144 ASSERT(status != 0);
145 bitmapRowPitch = static_cast<int>(header.bmWidthBytes);
146}
147
148void Win32SurfaceKHR::destroyFrameBuffer()
149{
150 SelectObject(bitmapContext, NULL);
151 DeleteObject(bitmap);
152 bitmap = {};
153 bitmapRowPitch = 0;
154 framebuffer = nullptr;
Nicolas Capensd3545372019-08-09 13:59:18 -0400155}
156
157}