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