18 #include "dtool_config.h"
27 #ifndef MAXIMUM_PROCESSORS
28 #define MAXIMUM_PROCESSORS 32
31 typedef enum _Process_DPI_Awareness {
32 Process_DPI_Unaware = 0,
33 Process_System_DPI_Aware = 1,
34 Process_Per_Monitor_DPI_Aware = 2
35 } Process_DPI_Awareness;
37 typedef struct _PROCESSOR_POWER_INFORMATION {
43 ULONG CurrentIdleState;
44 } PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
46 typedef BOOL (WINAPI *GetProcessMemoryInfoType) (HANDLE Process, PROCESS_MEMORY_COUNTERS *ppsmemCounters, DWORD cb);
47 typedef long (__stdcall *CallNtPowerInformationType) (POWER_INFORMATION_LEVEL information_level, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
49 static int initialize =
false;
50 static HMODULE psapi_dll = 0;
51 static GetProcessMemoryInfoType GetProcessMemoryInfoFunction = 0;
52 static CallNtPowerInformationType CallNtPowerInformationFunction = 0;
55 if (initialize ==
false) {
56 psapi_dll = LoadLibrary(
"psapi.dll");
58 GetProcessMemoryInfoFunction = (GetProcessMemoryInfoType) GetProcAddress(psapi_dll,
"GetProcessMemoryInfo");
64 MEMORYSTATUSEX memory_status;
66 memory_status.dwLength =
sizeof(MEMORYSTATUSEX);
67 if (GlobalMemoryStatusEx(&memory_status)) {
68 display_information->_physical_memory = memory_status.ullTotalPhys;
69 display_information->_available_physical_memory = memory_status.ullAvailPhys;
70 display_information->_page_file_size = memory_status.ullTotalPageFile;
71 display_information->_available_page_file_size = memory_status.ullAvailPageFile;
72 display_information->_process_virtual_memory = memory_status.ullTotalVirtual;
73 display_information->_available_process_virtual_memory = memory_status.ullAvailVirtual;
74 display_information->_memory_load = memory_status.dwMemoryLoad;
77 if (GetProcessMemoryInfoFunction) {
80 PROCESS_MEMORY_COUNTERS process_memory_counters;
82 process_id = GetCurrentProcessId();
83 process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id);
85 if (GetProcessMemoryInfoFunction (process, &process_memory_counters,
sizeof(PROCESS_MEMORY_COUNTERS))) {
86 display_information->_page_fault_count = process_memory_counters.PageFaultCount;
87 display_information->_process_memory = process_memory_counters.WorkingSetSize;
88 display_information->_peak_process_memory = process_memory_counters.PeakWorkingSetSize;
89 display_information->_page_file_usage = process_memory_counters.PagefileUsage;
90 display_information->_peak_page_file_usage = process_memory_counters.PeakPagefileUsage;
98 int update_cpu_frequency_function(
int processor_number,
DisplayInformation *display_information) {
102 display_information->_maximum_cpu_frequency = 0;
103 display_information->_current_cpu_frequency = 0;
105 if (CallNtPowerInformationFunction) {
110 ULONG input_buffer_size;
111 ULONG output_buffer_size;
112 POWER_INFORMATION_LEVEL information_level;
113 PROCESSOR_POWER_INFORMATION *processor_power_information;
114 PROCESSOR_POWER_INFORMATION processor_power_information_array [MAXIMUM_PROCESSORS];
116 memset(processor_power_information_array, 0,
sizeof(PROCESSOR_POWER_INFORMATION) * MAXIMUM_PROCESSORS);
118 processor_power_information = processor_power_information_array;
119 for (i = 0; i < MAXIMUM_PROCESSORS; i++) {
120 processor_power_information->Number = 0xFFFFFFFF;
121 processor_power_information++;
124 information_level = ProcessorInformation;
125 input_buffer =
nullptr;
126 output_buffer = processor_power_information_array;
127 input_buffer_size = 0;
128 output_buffer_size =
sizeof(PROCESSOR_POWER_INFORMATION) * MAXIMUM_PROCESSORS;
129 if (CallNtPowerInformationFunction(information_level, input_buffer, input_buffer_size, output_buffer, output_buffer_size) == 0) {
130 processor_power_information = processor_power_information_array;
131 for (i = 0; i < MAXIMUM_PROCESSORS; i++) {
132 if (processor_power_information->Number == processor_number) {
135 value = processor_power_information->MaxMhz;
136 display_information->_maximum_cpu_frequency = value * 1000000;
138 value = processor_power_information->CurrentMhz;
139 display_information->_current_cpu_frequency = value * 1000000;
145 processor_power_information++;
155 int num_cpu_cores = 0;
156 int num_logical_cpus = 0;
159 typedef BOOL (WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,
162 glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT(
"kernel32")),
163 "GetLogicalProcessorInformation");
164 if (glpi ==
nullptr) {
165 windisplay_cat.info()
166 <<
"GetLogicalProcessorInformation is not supported.\n";
172 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer =
nullptr;
173 DWORD buffer_length = 0;
174 DWORD rc = glpi(buffer, &buffer_length);
176 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
177 if (buffer !=
nullptr) {
178 PANDA_FREE_ARRAY(buffer);
181 buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)PANDA_MALLOC_ARRAY(buffer_length);
182 nassertv(buffer !=
nullptr);
184 windisplay_cat.info()
185 <<
"GetLogicalProcessorInformation failed: " << GetLastError()
189 rc = glpi(buffer, &buffer_length);
193 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer;
194 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION end = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)((
char *)buffer + buffer_length);
197 if (ptr->Relationship == RelationProcessorCore) {
206 PANDA_FREE_ARRAY(buffer);
208 windisplay_cat.info()
209 << num_cpu_cores <<
" CPU cores, with "
210 << num_logical_cpus <<
" logical processors.\n";
212 display_information->_num_cpu_cores = num_cpu_cores;
213 display_information->_num_logical_cpus = num_logical_cpus;
224 _supported_types = OT_window | OT_fullscreen_window;
226 HMODULE user32 = GetModuleHandleA(
"user32.dll");
227 if (user32 !=
nullptr) {
229 typedef HRESULT (WINAPI *PFN_SETPROCESSDPIAWARENESS)(Process_DPI_Awareness);
230 PFN_SETPROCESSDPIAWARENESS pfnSetProcessDpiAwareness =
231 (PFN_SETPROCESSDPIAWARENESS)GetProcAddress(user32,
"SetProcessDpiAwarenessInternal");
233 if (pfnSetProcessDpiAwareness ==
nullptr) {
234 if (windisplay_cat.is_debug()) {
235 windisplay_cat.debug() <<
"Unable to find SetProcessDpiAwareness in user32.dll.\n";
238 if (windisplay_cat.is_debug()) {
239 windisplay_cat.debug() <<
"Calling SetProcessDpiAwareness().\n";
241 pfnSetProcessDpiAwareness(Process_Per_Monitor_DPI_Aware);
243 HDC dc = GetDC(
nullptr);
245 int dpi = GetDeviceCaps(dc, LOGPIXELSX);
247 PN_stdfloat zoom = (double)dpi / 96.0;
248 set_detected_display_zoom(zoom);
250 if (windisplay_cat.is_debug()) {
251 windisplay_cat.debug()
252 <<
"Determined display zoom to be " << zoom
253 <<
" based on LOGPIXELSX " << dpi <<
"\n";
256 ReleaseDC(
nullptr, dc);
264 if (request_dxdisplay_information) {
265 if (windisplay_cat.is_debug()) {
266 windisplay_cat.debug() <<
"Using Direct3D 9 to fetch display information.\n";
270 dx9_display_information(display_search_parameters_dx9, _display_information);
275 if (windisplay_cat.is_debug()) {
276 windisplay_cat.debug() <<
"Using EnumDisplaySettings to fetch display information.\n";
280 dm.dmSize =
sizeof(dm);
281 for (
int i = 0; EnumDisplaySettings(
nullptr, i, &dm) != 0; ++i) {
283 mode.width = dm.dmPelsWidth;
284 mode.height = dm.dmPelsHeight;
285 mode.bits_per_pixel = dm.dmBitsPerPel;
286 mode.refresh_rate = dm.dmDisplayFrequency;
287 mode.fullscreen_only = 0;
288 if (i == 0 || mode != display_modes.back()) {
289 display_modes.push_back(mode);
294 _display_information->_total_display_modes = display_modes.size();
295 if (!display_modes.empty()) {
296 _display_information->_display_mode_array =
new DisplayMode[display_modes.size()];
297 std::copy(display_modes.begin(), display_modes.end(),
298 _display_information->_display_mode_array);
306 OSVERSIONINFO version_info;
308 version_info.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
309 if (GetVersionEx(&version_info)) {
310 if (windisplay_cat.is_info()) {
311 sprintf(
string,
"OS version: %lu.%lu.%lu.%lu\n", version_info.dwMajorVersion, version_info.dwMinorVersion, version_info.dwPlatformId, version_info.dwBuildNumber);
312 windisplay_cat.info() << string;
313 windisplay_cat.info() <<
" " << version_info.szCSDVersion <<
"\n";
316 _display_information->_os_version_major = version_info.dwMajorVersion;
317 _display_information->_os_version_minor = version_info.dwMinorVersion;
318 _display_information->_os_version_build = version_info.dwBuildNumber;
319 _display_information->_os_platform_id = version_info.dwPlatformId;
322 _display_width = GetSystemMetrics(SM_CXSCREEN);
323 _display_height = GetSystemMetrics(SM_CYSCREEN);
327 power_dll = LoadLibrary(
"PowrProf.dll");
329 CallNtPowerInformationFunction = (CallNtPowerInformationType) GetProcAddress(power_dll,
"CallNtPowerInformation");
330 if (CallNtPowerInformationFunction) {
332 _display_information->_update_cpu_frequency_function = update_cpu_frequency_function;
333 update_cpu_frequency_function(0, _display_information);
335 sprintf(
string,
"max Mhz %I64d, current Mhz %I64d\n", _display_information->_maximum_cpu_frequency, _display_information->_current_cpu_frequency);
337 windisplay_cat.info() << string;
352 _display_information->_get_memory_information_function = get_memory_information;
357 LARGE_INTEGER counter;
359 LARGE_INTEGER frequency;
363 counter.QuadPart = 0;
365 frequency.QuadPart = 0;
370 windisplay_cat.info() <<
"begin QueryPerformanceFrequency\n";
371 thread = GetCurrentThread();
372 priority = GetThreadPriority (thread);
373 SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL);
375 if (QueryPerformanceFrequency(&frequency)) {
376 if (frequency.QuadPart > 0) {
377 if (QueryPerformanceCounter (&counter)) {
379 end.QuadPart = counter.QuadPart + frequency.QuadPart;
380 while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
383 end_time = __rdtsc();
385 _display_information->_cpu_frequency = end_time - time;
390 SetThreadPriority(thread, priority);
391 sprintf(
string,
"QueryPerformanceFrequency: %I64d\n", frequency.QuadPart);
392 windisplay_cat.info() << string;
393 sprintf(
string,
"CPU frequency: %I64d\n", _display_information->_cpu_frequency);
394 windisplay_cat.info() << string;
397 count_number_of_cpus(_display_information);