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