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