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);
Parameters used for searching display capabilities.
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.
This is our own Panda specialization on the default STL vector.
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.