1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
4 *
5 * Copyright 2016 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Win32 Vulkan platform
22 *//*--------------------------------------------------------------------*/
23
24 #include "tcuWin32VulkanPlatform.hpp"
25 #include "tcuWin32Window.hpp"
26
27 #include "tcuFormatUtil.hpp"
28 #include "tcuFunctionLibrary.hpp"
29 #include "tcuVector.hpp"
30
31 #include "vkWsiPlatform.hpp"
32
33 #include "deUniquePtr.hpp"
34 #include "deMemory.h"
35
36 namespace tcu
37 {
38 namespace win32
39 {
40
41 using de::MovePtr;
42 using de::UniquePtr;
43
44 DE_STATIC_ASSERT(sizeof(vk::pt::Win32InstanceHandle) == sizeof(HINSTANCE));
45 DE_STATIC_ASSERT(sizeof(vk::pt::Win32WindowHandle) == sizeof(HWND));
46
47 class VulkanWindow : public vk::wsi::Win32WindowInterface
48 {
49 public:
VulkanWindow(MovePtr<win32::Window> window)50 VulkanWindow(MovePtr<win32::Window> window)
51 : vk::wsi::Win32WindowInterface(vk::pt::Win32WindowHandle(window->getHandle()))
52 , m_window(window)
53 {
54 }
55
setVisible(bool visible)56 void setVisible(bool visible)
57 {
58 m_window->setVisible(visible);
59 }
60
setForeground(void)61 void setForeground(void)
62 {
63 m_window->setForeground();
64 }
65
resize(const UVec2 & newSize)66 void resize(const UVec2 &newSize)
67 {
68 m_window->setSize((int)newSize.x(), (int)newSize.y());
69 }
70
setMinimized(bool minimized)71 void setMinimized(bool minimized)
72 {
73 m_window->setMinimized(minimized);
74 }
75
76 private:
77 UniquePtr<win32::Window> m_window;
78 };
79
80 class VulkanDisplay : public vk::wsi::Win32DisplayInterface
81 {
82 public:
VulkanDisplay(HINSTANCE instance)83 VulkanDisplay(HINSTANCE instance) : vk::wsi::Win32DisplayInterface(vk::pt::Win32InstanceHandle(instance))
84 {
85 }
86
createWindow(const Maybe<UVec2> & initialSize) const87 vk::wsi::Window *createWindow(const Maybe<UVec2> &initialSize) const
88 {
89 const HINSTANCE instance = (HINSTANCE)m_native.internal;
90 const uint32_t width = !initialSize ? 400 : initialSize->x();
91 const uint32_t height = !initialSize ? 300 : initialSize->y();
92
93 return new VulkanWindow(MovePtr<win32::Window>(new win32::Window(instance, (int)width, (int)height)));
94 }
95 };
96
97 class VulkanLibrary : public vk::Library
98 {
99 public:
VulkanLibrary(const char * libraryPath)100 VulkanLibrary(const char *libraryPath)
101 : m_library(libraryPath != DE_NULL ? libraryPath : "vulkan-1.dll")
102 , m_driver(m_library)
103 {
104 }
105
getPlatformInterface(void) const106 const vk::PlatformInterface &getPlatformInterface(void) const
107 {
108 return m_driver;
109 }
getFunctionLibrary(void) const110 const tcu::FunctionLibrary &getFunctionLibrary(void) const
111 {
112 return m_library;
113 }
114
115 private:
116 const tcu::DynamicFunctionLibrary m_library;
117 const vk::PlatformDriver m_driver;
118 };
119
VulkanPlatform(HINSTANCE instance)120 VulkanPlatform::VulkanPlatform(HINSTANCE instance) : m_instance(instance)
121 {
122 }
123
~VulkanPlatform(void)124 VulkanPlatform::~VulkanPlatform(void)
125 {
126 }
127
createLibrary(LibraryType libraryType,const char * libraryPath) const128 vk::Library *VulkanPlatform::createLibrary(LibraryType libraryType, const char *libraryPath) const
129 {
130 switch (libraryType)
131 {
132 case LIBRARY_TYPE_VULKAN:
133 return new VulkanLibrary(libraryPath);
134 default:
135 TCU_THROW(InternalError, "Unknown library type requested");
136 }
137 }
138
getStringRegKey(const std::string & regKey,const std::string & strValueName,std::string & strValue)139 ULONG getStringRegKey(const std::string ®Key, const std::string &strValueName, std::string &strValue)
140 {
141 HKEY hKey;
142 ULONG nError;
143 CHAR szBuffer[512];
144 DWORD dwBufferSize = sizeof(szBuffer);
145
146 nError = RegOpenKeyExA(HKEY_LOCAL_MACHINE, regKey.c_str(), 0, KEY_READ, &hKey);
147
148 if (ERROR_SUCCESS == nError)
149 nError = RegQueryValueExA(hKey, strValueName.c_str(), 0, DE_NULL, (LPBYTE)szBuffer, &dwBufferSize);
150
151 if (ERROR_SUCCESS == nError)
152 strValue = szBuffer;
153
154 return nError;
155 }
156
getWindowsBits(std::ostream & dst)157 void getWindowsBits(std::ostream &dst)
158 {
159 #if defined(_WIN64)
160 dst << "64"; // 64-bit programs run only on Win64
161 return;
162 #elif defined(_WIN32)
163 BOOL is64 = false;
164 // 32-bit programs run on both 32-bit and 64-bit Windows.
165 // Function is defined from XP SP2 onwards, so we don't need to
166 // check if it exists.
167 if (IsWow64Process(GetCurrentProcess(), &is64))
168 {
169 if (is64)
170 dst << "64";
171 else
172 dst << "32";
173 return;
174 }
175 #endif
176 #if !defined(_WIN64)
177 // IsWow64Process returns failure or neither of
178 // _WIN64 or _WIN32 is defined
179 dst << "Unknown";
180 #endif
181 }
182
getOSNameFromRegistry(std::ostream & dst)183 void getOSNameFromRegistry(std::ostream &dst)
184 {
185 const char *keypath = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
186 std::string productname = "Unknown";
187 std::string releaseid = "Unknown";
188 std::string optional;
189
190 getStringRegKey(keypath, "ProductName", productname);
191 getStringRegKey(keypath, "ReleaseId", releaseid);
192
193 getWindowsBits(dst);
194
195 dst << " bit Windows Product: " << productname << ", Release: " << releaseid;
196
197 if (ERROR_SUCCESS == getStringRegKey(keypath, "EditionID", optional))
198 {
199 dst << ", Edition: " << optional;
200 if (ERROR_SUCCESS == getStringRegKey(keypath, "EditionSubstring", optional) && optional.length() > 0)
201 dst << " " << optional;
202 }
203 }
204
getOSVersionFromDLL(std::ostream & dst)205 void getOSVersionFromDLL(std::ostream &dst)
206 {
207 DWORD buffer_size = GetFileVersionInfoSize(("kernel32.dll"), DE_NULL);
208 char *buffer = 0;
209
210 if (buffer_size != 0)
211 {
212 buffer = new char[buffer_size];
213 if (buffer != 0)
214 {
215 if (GetFileVersionInfo("kernel32.dll", 0, buffer_size, buffer))
216 {
217 VS_FIXEDFILEINFO *version = DE_NULL;
218 UINT version_len = 0;
219
220 if (VerQueryValue(buffer, "\\", (LPVOID *)&version, &version_len))
221 {
222 dst << ", DLL Version: " << HIWORD(version->dwProductVersionMS) << "."
223 << LOWORD(version->dwProductVersionMS) << ", DLL Build: " << HIWORD(version->dwProductVersionLS)
224 << "." << LOWORD(version->dwProductVersionLS);
225 }
226 }
227 delete[] buffer;
228 }
229 }
230 }
231
232 // Old windows version query APIs lie about the version number. There's no replacement
233 // API, and instead applications are supposed to queriy about capabilities instead of
234 // relying on operating system version numbers.
235 //
236 // Since we want to actually know the version number for debugging purposes, we need
237 // to use roundabout ways to fetch the information.
238 //
239 // The registry contains some useful strings, which we print out if the keys
240 // are available. The current official way to get version number is to look at a
241 // system DLL file and read its version number, so we do that too, in case the
242 // registry becomes unreliable in the future.
243 //
244 // If the DLL method fails, we simply don't print out anything about it.
245 // The minimal output from this function is "Windows Product: Unknown, Release: Unknown"
getOSInfo(std::ostream & dst)246 static void getOSInfo(std::ostream &dst)
247 {
248 getOSNameFromRegistry(dst);
249 getOSVersionFromDLL(dst);
250 }
251
getProcessorArchitectureName(WORD arch)252 const char *getProcessorArchitectureName(WORD arch)
253 {
254 switch (arch)
255 {
256 case PROCESSOR_ARCHITECTURE_AMD64:
257 return "AMD64";
258 case PROCESSOR_ARCHITECTURE_ARM:
259 return "ARM";
260 case PROCESSOR_ARCHITECTURE_IA64:
261 return "IA64";
262 case PROCESSOR_ARCHITECTURE_INTEL:
263 return "INTEL";
264 case PROCESSOR_ARCHITECTURE_UNKNOWN:
265 return "UNKNOWN";
266 default:
267 return DE_NULL;
268 }
269 }
270
getProcessorInfo(std::ostream & dst)271 static void getProcessorInfo(std::ostream &dst)
272 {
273 SYSTEM_INFO sysInfo;
274
275 deMemset(&sysInfo, 0, sizeof(sysInfo));
276 GetSystemInfo(&sysInfo);
277
278 dst << "arch ";
279 {
280 const char *const archName = getProcessorArchitectureName(sysInfo.wProcessorArchitecture);
281
282 if (archName)
283 dst << archName;
284 else
285 dst << tcu::toHex(sysInfo.wProcessorArchitecture);
286 }
287
288 dst << ", level " << tcu::toHex(sysInfo.wProcessorLevel) << ", revision " << tcu::toHex(sysInfo.wProcessorRevision);
289 }
290
describePlatform(std::ostream & dst) const291 void VulkanPlatform::describePlatform(std::ostream &dst) const
292 {
293 dst << "OS: ";
294 getOSInfo(dst);
295 dst << "\n";
296
297 dst << "CPU: ";
298 getProcessorInfo(dst);
299 dst << "\n";
300 }
301
createWsiDisplay(vk::wsi::Type wsiType) const302 vk::wsi::Display *VulkanPlatform::createWsiDisplay(vk::wsi::Type wsiType) const
303 {
304 if (wsiType != vk::wsi::TYPE_WIN32)
305 TCU_THROW(NotSupportedError, "WSI type not supported");
306
307 return new VulkanDisplay(m_instance);
308 }
309
hasDisplay(vk::wsi::Type wsiType) const310 bool VulkanPlatform::hasDisplay(vk::wsi::Type wsiType) const
311 {
312 if (wsiType != vk::wsi::TYPE_WIN32)
313 return false;
314
315 return true;
316 }
317
318 } // namespace win32
319 } // namespace tcu
320