• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &regKey, 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