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// \todo [2016-01-22 pyry] GetVersionEx() used by getOSInfo() is deprecated.
25//						   Find a way to get version info without using deprecated APIs.
26#pragma warning(disable : 4996)
27
28#include "tcuWin32VulkanPlatform.hpp"
29#include "tcuWin32Window.hpp"
30
31#include "tcuFormatUtil.hpp"
32#include "tcuFunctionLibrary.hpp"
33#include "tcuVector.hpp"
34
35#include "vkWsiPlatform.hpp"
36
37#include "deUniquePtr.hpp"
38#include "deMemory.h"
39
40namespace tcu
41{
42namespace win32
43{
44
45using de::MovePtr;
46using de::UniquePtr;
47
48DE_STATIC_ASSERT(sizeof(vk::pt::Win32InstanceHandle)	== sizeof(HINSTANCE));
49DE_STATIC_ASSERT(sizeof(vk::pt::Win32WindowHandle)		== sizeof(HWND));
50
51class VulkanWindow : public vk::wsi::Win32WindowInterface
52{
53public:
54	VulkanWindow (MovePtr<win32::Window> window)
55		: vk::wsi::Win32WindowInterface	(vk::pt::Win32WindowHandle(window->getHandle()))
56		, m_window						(window)
57	{
58	}
59
60	void resize (const UVec2& newSize)
61	{
62		m_window->setSize((int)newSize.x(), (int)newSize.y());
63	}
64
65private:
66	UniquePtr<win32::Window>	m_window;
67};
68
69class VulkanDisplay : public vk::wsi::Win32DisplayInterface
70{
71public:
72	VulkanDisplay (HINSTANCE instance)
73		: vk::wsi::Win32DisplayInterface	(vk::pt::Win32InstanceHandle(instance))
74	{
75	}
76
77	vk::wsi::Window* createWindow (const Maybe<UVec2>& initialSize) const
78	{
79		const HINSTANCE	instance	= (HINSTANCE)m_native.internal;
80		const deUint32	width		= !initialSize ? 400 : initialSize->x();
81		const deUint32	height		= !initialSize ? 300 : initialSize->y();
82
83		return new VulkanWindow(MovePtr<win32::Window>(new win32::Window(instance, (int)width, (int)height)));
84	}
85};
86
87class VulkanLibrary : public vk::Library
88{
89public:
90	VulkanLibrary (void)
91		: m_library	("vulkan-1.dll")
92		, m_driver	(m_library)
93	{
94	}
95
96	const vk::PlatformInterface& getPlatformInterface (void) const
97	{
98		return m_driver;
99	}
100
101private:
102	const tcu::DynamicFunctionLibrary	m_library;
103	const vk::PlatformDriver			m_driver;
104};
105
106VulkanPlatform::VulkanPlatform (HINSTANCE instance)
107	: m_instance(instance)
108{
109}
110
111VulkanPlatform::~VulkanPlatform (void)
112{
113}
114
115vk::Library* VulkanPlatform::createLibrary (void) const
116{
117	return new VulkanLibrary();
118}
119
120const char* getProductTypeName (WORD productType)
121{
122	switch (productType)
123	{
124		case VER_NT_DOMAIN_CONTROLLER:	return "Windows Server (domain controller)";
125		case VER_NT_SERVER:				return "Windows Server";
126		case VER_NT_WORKSTATION:		return "Windows NT";
127		default:						return DE_NULL;
128	}
129}
130
131static void getOSInfo (std::ostream& dst)
132{
133	OSVERSIONINFOEX	osInfo;
134
135	deMemset(&osInfo, 0, sizeof(osInfo));
136	osInfo.dwOSVersionInfoSize = (DWORD)sizeof(osInfo);
137
138	GetVersionEx((OSVERSIONINFO*)&osInfo);
139
140	{
141		const char* const	productName	= getProductTypeName(osInfo.wProductType);
142
143		if (productName)
144			dst << productName;
145		else
146			dst << "unknown product " << tcu::toHex(osInfo.wProductType);
147	}
148
149	dst << " " << osInfo.dwMajorVersion << "." << osInfo.dwMinorVersion
150		<< ", service pack " << osInfo.wServicePackMajor << "." << osInfo.wServicePackMinor
151		<< ", build " << osInfo.dwBuildNumber;
152}
153
154const char* getProcessorArchitectureName (WORD arch)
155{
156	switch (arch)
157	{
158		case PROCESSOR_ARCHITECTURE_AMD64:		return "AMD64";
159		case PROCESSOR_ARCHITECTURE_ARM:		return "ARM";
160		case PROCESSOR_ARCHITECTURE_IA64:		return "IA64";
161		case PROCESSOR_ARCHITECTURE_INTEL:		return "INTEL";
162		case PROCESSOR_ARCHITECTURE_UNKNOWN:	return "UNKNOWN";
163		default:								return DE_NULL;
164	}
165}
166
167static void getProcessorInfo (std::ostream& dst)
168{
169	SYSTEM_INFO	sysInfo;
170
171	deMemset(&sysInfo, 0, sizeof(sysInfo));
172	GetSystemInfo(&sysInfo);
173
174	dst << "arch ";
175	{
176		const char* const	archName	= getProcessorArchitectureName(sysInfo.wProcessorArchitecture);
177
178		if (archName)
179			dst << archName;
180		else
181			dst << tcu::toHex(sysInfo.wProcessorArchitecture);
182	}
183
184	dst << ", level " << tcu::toHex(sysInfo.wProcessorLevel) << ", revision " << tcu::toHex(sysInfo.wProcessorRevision);
185}
186
187void VulkanPlatform::describePlatform (std::ostream& dst) const
188{
189	dst << "OS: ";
190	getOSInfo(dst);
191	dst << "\n";
192
193	dst << "CPU: ";
194	getProcessorInfo(dst);
195	dst << "\n";
196}
197
198void VulkanPlatform::getMemoryLimits (vk::PlatformMemoryLimits& limits) const
199{
200	limits.totalSystemMemory					= 256*1024*1024;
201	limits.totalDeviceLocalMemory				= 128*1024*1024;
202	limits.deviceMemoryAllocationGranularity	= 64*1024;
203	limits.devicePageSize						= 4096;
204	limits.devicePageTableEntrySize				= 8;
205	limits.devicePageTableHierarchyLevels		= 3;
206}
207
208vk::wsi::Display* VulkanPlatform::createWsiDisplay (vk::wsi::Type wsiType) const
209{
210	if (wsiType != vk::wsi::TYPE_WIN32)
211		TCU_THROW(NotSupportedError, "WSI type not supported");
212
213	return new VulkanDisplay(m_instance);
214}
215
216} // win32
217} // tcu
218