18#include "dtool_config.h"
27#ifndef MAXIMUM_PROCESSORS
28#define MAXIMUM_PROCESSORS 32
31typedef 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;
37typedef struct _PROCESSOR_POWER_INFORMATION {
43 ULONG CurrentIdleState;
44} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
46typedef BOOL (WINAPI *GetProcessMemoryInfoType) (HANDLE Process, PROCESS_MEMORY_COUNTERS *ppsmemCounters, DWORD cb);
47typedef long (__stdcall *CallNtPowerInformationType) (POWER_INFORMATION_LEVEL information_level, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
49static int initialize =
false;
50static HMODULE psapi_dll = 0;
51static GetProcessMemoryInfoType GetProcessMemoryInfoFunction = 0;
52static 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;
98int 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);
262 if (windisplay_cat.is_debug()) {
263 windisplay_cat.debug()
264 <<
"Detected display devices:\n";
266 DISPLAY_DEVICEA device;
267 device.cb =
sizeof(device);
268 for (DWORD devnum = 0; EnumDisplayDevicesA(
nullptr, devnum, &device, 0); ++devnum) {
269 std::ostream &out = windisplay_cat.debug();
270 out <<
" " << device.DeviceName <<
" [" << device.DeviceString <<
"]";
271 if (device.StateFlags & DISPLAY_DEVICE_ACTIVE) {
274 if (device.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) {
275 out <<
" (multi-driver)";
277 if (device.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
280 if (device.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) {
281 out <<
" (mirroring)";
283 if (device.StateFlags & DISPLAY_DEVICE_REMOVABLE) {
284 out <<
" (removable)";
289 int nmonitor = GetSystemMetrics(SM_CMONITORS);
290 windisplay_cat.debug()
291 <<
"Detected " << nmonitor <<
" monitors, "
292 << (GetSystemMetrics(SM_SAMEDISPLAYFORMAT) != 0 ?
"" :
"NOT ")
293 <<
"sharing same display format:\n";
298 [](HMONITOR monitor, HDC dc, LPRECT rect, LPARAM param) -> BOOL {
300 info.cbSize =
sizeof(info);
301 if (GetMonitorInfoA(monitor, &info)) {
302 std::ostream &out = windisplay_cat.debug() <<
" ";
304 DISPLAY_DEVICEA device;
305 device.cb =
sizeof(device);
306 device.StateFlags = 0;
307 if (EnumDisplayDevicesA(info.szDevice, 0, &device, 0)) {
308 out << device.DeviceName <<
" [" << device.DeviceString <<
"]";
311 out << info.szDevice <<
" (device enum failed)";
314 if (info.dwFlags & MONITORINFOF_PRIMARY) {
317 if (info.rcWork.left != 0 || info.rcWork.top != 0) {
318 out <<
" (at " << info.rcWork.left <<
"x" << info.rcWork.top <<
")";
329 if (request_dxdisplay_information) {
330 if (windisplay_cat.is_debug()) {
331 windisplay_cat.debug() <<
"Using Direct3D 9 to fetch display information.\n";
333 DisplaySearchParameters display_search_parameters_dx9;
334 int dx9_display_information (DisplaySearchParameters &display_search_parameters_dx9, DisplayInformation *display_information);
335 dx9_display_information(display_search_parameters_dx9, _display_information);
340 if (windisplay_cat.is_debug()) {
341 windisplay_cat.debug() <<
"Using EnumDisplaySettings to fetch display information.\n";
344 pvector<DisplayMode> display_modes;
345 DisplayMode current_mode = {0};
346 int current_mode_index = -1;
348 dm.dmSize =
sizeof(dm);
350 if (EnumDisplaySettings(
nullptr, ENUM_CURRENT_SETTINGS, &dm) != 0) {
351 current_mode.width = dm.dmPelsWidth;
352 current_mode.height = dm.dmPelsHeight;
353 current_mode.bits_per_pixel = dm.dmBitsPerPel;
354 current_mode.refresh_rate = dm.dmDisplayFrequency;
355 current_mode.fullscreen_only = 0;
358 for (
int i = 0; EnumDisplaySettings(
nullptr, i, &dm) != 0; ++i) {
360 mode.width = dm.dmPelsWidth;
361 mode.height = dm.dmPelsHeight;
362 mode.bits_per_pixel = dm.dmBitsPerPel;
363 mode.refresh_rate = dm.dmDisplayFrequency;
364 mode.fullscreen_only = 0;
365 if (i == 0 || mode != display_modes.back()) {
366 if (current_mode_index < 0 && mode == current_mode) {
367 current_mode_index = (int)display_modes.size();
369 display_modes.push_back(mode);
374 _display_information->_total_display_modes = display_modes.size();
375 if (!display_modes.empty()) {
376 _display_information->_current_display_mode_index = current_mode_index;
377 _display_information->_display_mode_array =
new DisplayMode[display_modes.size()];
378 std::copy(display_modes.begin(), display_modes.end(),
379 _display_information->_display_mode_array);
387 OSVERSIONINFO version_info;
389 version_info.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
390 if (GetVersionEx(&version_info)) {
391 if (windisplay_cat.is_info()) {
392 sprintf(
string,
"OS version: %lu.%lu.%lu.%lu\n", version_info.dwMajorVersion, version_info.dwMinorVersion, version_info.dwPlatformId, version_info.dwBuildNumber);
393 windisplay_cat.info() << string;
394 windisplay_cat.info() <<
" " << version_info.szCSDVersion <<
"\n";
397 _display_information->_os_version_major = version_info.dwMajorVersion;
398 _display_information->_os_version_minor = version_info.dwMinorVersion;
399 _display_information->_os_version_build = version_info.dwBuildNumber;
400 _display_information->_os_platform_id = version_info.dwPlatformId;
403 _display_width = GetSystemMetrics(SM_CXSCREEN);
404 _display_height = GetSystemMetrics(SM_CYSCREEN);
408 power_dll = LoadLibrary(
"PowrProf.dll");
410 CallNtPowerInformationFunction = (CallNtPowerInformationType) GetProcAddress(power_dll,
"CallNtPowerInformation");
411 if (CallNtPowerInformationFunction) {
413 _display_information->_update_cpu_frequency_function = update_cpu_frequency_function;
414 update_cpu_frequency_function(0, _display_information);
416 sprintf(
string,
"max Mhz %I64d, current Mhz %I64d\n", _display_information->_maximum_cpu_frequency, _display_information->_current_cpu_frequency);
418 windisplay_cat.info() << string;
433 _display_information->_get_memory_information_function = get_memory_information;
438 LARGE_INTEGER counter;
440 LARGE_INTEGER frequency;
444 counter.QuadPart = 0;
446 frequency.QuadPart = 0;
451 windisplay_cat.info() <<
"begin QueryPerformanceFrequency\n";
452 thread = GetCurrentThread();
453 priority = GetThreadPriority (thread);
454 SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL);
456 if (QueryPerformanceFrequency(&frequency)) {
457 if (frequency.QuadPart > 0) {
458 if (QueryPerformanceCounter (&counter)) {
460 end.QuadPart = counter.QuadPart + frequency.QuadPart;
461 while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
464 end_time = __rdtsc();
466 _display_information->_cpu_frequency = end_time - time;
471 SetThreadPriority(thread, priority);
472 sprintf(
string,
"QueryPerformanceFrequency: %I64d\n", frequency.QuadPart);
473 windisplay_cat.info() <<
string;
474 sprintf(
string,
"CPU frequency: %I64d\n", _display_information->_cpu_frequency);
475 windisplay_cat.info() <<
string;
478 count_number_of_cpus(_display_information);
TypeHandle is the identifier used to differentiate C++ class types.
virtual void lookup_cpu_data()
Looks up the detailed CPU information and stores it in _display_information, if supported by the OS.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int count_bits_in_word(unsigned short x)
Returns the number of 1 bits in the indicated word.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.