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);
248 if (request_dxdisplay_information) {
249 if (windisplay_cat.is_debug()) {
250 windisplay_cat.debug() <<
"Using Direct3D 9 to fetch display information.\n";
254 dx9_display_information(display_search_parameters_dx9, _display_information);
259 if (windisplay_cat.is_debug()) {
260 windisplay_cat.debug() <<
"Using EnumDisplaySettings to fetch display information.\n";
264 dm.dmSize =
sizeof(dm);
265 for (
int i = 0; EnumDisplaySettings(
nullptr, i, &dm) != 0; ++i) {
267 mode.width = dm.dmPelsWidth;
268 mode.height = dm.dmPelsHeight;
269 mode.bits_per_pixel = dm.dmBitsPerPel;
270 mode.refresh_rate = dm.dmDisplayFrequency;
271 mode.fullscreen_only = 0;
272 if (i == 0 || mode != display_modes.back()) {
273 display_modes.push_back(mode);
278 _display_information->_total_display_modes = display_modes.size();
279 if (!display_modes.empty()) {
280 _display_information->_display_mode_array =
new DisplayMode[display_modes.size()];
281 std::copy(display_modes.begin(), display_modes.end(),
282 _display_information->_display_mode_array);
290 OSVERSIONINFO version_info;
292 version_info.dwOSVersionInfoSize =
sizeof(OSVERSIONINFO);
293 if (GetVersionEx(&version_info)) {
294 if (windisplay_cat.is_info()) {
295 sprintf(
string,
"OS version: %lu.%lu.%lu.%lu\n", version_info.dwMajorVersion, version_info.dwMinorVersion, version_info.dwPlatformId, version_info.dwBuildNumber);
296 windisplay_cat.info() << string;
297 windisplay_cat.info() <<
" " << version_info.szCSDVersion <<
"\n";
300 _display_information->_os_version_major = version_info.dwMajorVersion;
301 _display_information->_os_version_minor = version_info.dwMinorVersion;
302 _display_information->_os_version_build = version_info.dwBuildNumber;
303 _display_information->_os_platform_id = version_info.dwPlatformId;
306 _display_width = GetSystemMetrics(SM_CXSCREEN);
307 _display_height = GetSystemMetrics(SM_CYSCREEN);
311 power_dll = LoadLibrary(
"PowrProf.dll");
313 CallNtPowerInformationFunction = (CallNtPowerInformationType) GetProcAddress(power_dll,
"CallNtPowerInformation");
314 if (CallNtPowerInformationFunction) {
316 _display_information->_update_cpu_frequency_function = update_cpu_frequency_function;
317 update_cpu_frequency_function(0, _display_information);
319 sprintf(
string,
"max Mhz %I64d, current Mhz %I64d\n", _display_information->_maximum_cpu_frequency, _display_information->_current_cpu_frequency);
321 windisplay_cat.info() << string;
336 _display_information->_get_memory_information_function = get_memory_information;
341 LARGE_INTEGER counter;
343 LARGE_INTEGER frequency;
347 counter.QuadPart = 0;
349 frequency.QuadPart = 0;
354 windisplay_cat.info() <<
"begin QueryPerformanceFrequency\n";
355 thread = GetCurrentThread();
356 priority = GetThreadPriority (thread);
357 SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL);
359 if (QueryPerformanceFrequency(&frequency)) {
360 if (frequency.QuadPart > 0) {
361 if (QueryPerformanceCounter (&counter)) {
363 end.QuadPart = counter.QuadPart + frequency.QuadPart;
364 while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) {
367 end_time = __rdtsc();
369 _display_information->_cpu_frequency = end_time - time;
374 SetThreadPriority(thread, priority);
375 sprintf(
string,
"QueryPerformanceFrequency: %I64d\n", frequency.QuadPart);
376 windisplay_cat.info() << string;
377 sprintf(
string,
"CPU frequency: %I64d\n", _display_information->_cpu_frequency);
378 windisplay_cat.info() << string;
381 count_number_of_cpus(_display_information);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is our own Panda specialization on the default STL vector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Parameters used for searching display capabilities.
TypeHandle is the identifier used to differentiate C++ class types.
int count_bits_in_word(uint16_t x)
Returns the number of 1 bits in the indicated word.
virtual void lookup_cpu_data()
Looks up the detailed CPU information and stores it in _display_information, if supported by the OS.