Panda3D
|
00001 // Filename: winGraphicsPipe.cxx 00002 // Created by: drose (20Dec02) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "winGraphicsPipe.h" 00016 #include "config_windisplay.h" 00017 #include "displaySearchParameters.h" 00018 #include "dtool_config.h" 00019 #include "pbitops.h" 00020 00021 #include "psapi.h" 00022 #include "powrprof.h" 00023 00024 #ifdef _WIN64 00025 #include <intrin.h> 00026 #endif 00027 00028 00029 TypeHandle WinGraphicsPipe::_type_handle; 00030 00031 #define MAXIMUM_PROCESSORS 32 00032 00033 typedef struct _PROCESSOR_POWER_INFORMATION 00034 { 00035 ULONG Number; 00036 ULONG MaxMhz; 00037 ULONG CurrentMhz; 00038 ULONG MhzLimit; 00039 ULONG MaxIdleState; 00040 ULONG CurrentIdleState; 00041 } 00042 PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION; 00043 00044 typedef BOOL (WINAPI *GetProcessMemoryInfoType) (HANDLE Process, PROCESS_MEMORY_COUNTERS *ppsmemCounters, DWORD cb); 00045 typedef BOOL (WINAPI *GlobalMemoryStatusExType) (LPMEMORYSTATUSEX lpBuffer); 00046 typedef long (__stdcall *CallNtPowerInformationType) (POWER_INFORMATION_LEVEL information_level, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength); 00047 00048 static int initialize = false; 00049 static HMODULE psapi_dll = 0; 00050 static HMODULE kernel32_dll = 0; 00051 static HMODULE power_dll = 0; 00052 static GetProcessMemoryInfoType GetProcessMemoryInfoFunction = 0; 00053 static GlobalMemoryStatusExType GlobalMemoryStatusExFunction = 0; 00054 static CallNtPowerInformationType CallNtPowerInformationFunction = 0; 00055 00056 void get_memory_information (DisplayInformation *display_information) 00057 { 00058 if (initialize == false) { 00059 psapi_dll = LoadLibrary ("psapi.dll"); 00060 if (psapi_dll) { 00061 GetProcessMemoryInfoFunction = (GetProcessMemoryInfoType) GetProcAddress (psapi_dll, "GetProcessMemoryInfo"); 00062 } 00063 00064 kernel32_dll = LoadLibrary ("kernel32.dll"); 00065 if (kernel32_dll) { 00066 GlobalMemoryStatusExFunction = (GlobalMemoryStatusExType) GetProcAddress (kernel32_dll, "GlobalMemoryStatusEx"); 00067 } 00068 00069 initialize = true; 00070 } 00071 00072 if (GlobalMemoryStatusExFunction) { 00073 MEMORYSTATUSEX memory_status; 00074 00075 memory_status.dwLength = sizeof (MEMORYSTATUSEX); 00076 if (GlobalMemoryStatusExFunction (&memory_status)) { 00077 display_information -> _physical_memory = memory_status.ullTotalPhys; 00078 display_information -> _available_physical_memory = memory_status.ullAvailPhys; 00079 display_information -> _page_file_size = memory_status.ullTotalPageFile; 00080 display_information -> _available_page_file_size = memory_status.ullAvailPageFile; 00081 display_information -> _process_virtual_memory = memory_status.ullTotalVirtual; 00082 display_information -> _available_process_virtual_memory = memory_status.ullAvailVirtual; 00083 display_information -> _memory_load = memory_status.dwMemoryLoad; 00084 } 00085 } 00086 else { 00087 MEMORYSTATUS memory_status; 00088 00089 memory_status.dwLength = sizeof (MEMORYSTATUS); 00090 GlobalMemoryStatus (&memory_status); 00091 00092 display_information -> _physical_memory = memory_status.dwTotalPhys; 00093 display_information -> _available_physical_memory = memory_status.dwAvailPhys; 00094 display_information -> _page_file_size = memory_status.dwTotalPageFile; 00095 display_information -> _available_page_file_size = memory_status.dwAvailPageFile; 00096 display_information -> _process_virtual_memory = memory_status.dwTotalVirtual; 00097 display_information -> _available_process_virtual_memory = memory_status.dwAvailVirtual; 00098 display_information -> _memory_load = memory_status.dwMemoryLoad; 00099 } 00100 00101 if (GetProcessMemoryInfoFunction) { 00102 HANDLE process; 00103 DWORD process_id; 00104 PROCESS_MEMORY_COUNTERS process_memory_counters; 00105 00106 process_id = GetCurrentProcessId(); 00107 process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, process_id); 00108 if (process) { 00109 if (GetProcessMemoryInfoFunction (process, &process_memory_counters, sizeof (PROCESS_MEMORY_COUNTERS))) { 00110 display_information -> _page_fault_count = process_memory_counters.PageFaultCount; 00111 display_information -> _process_memory = process_memory_counters.WorkingSetSize; 00112 display_information -> _peak_process_memory = process_memory_counters.PeakWorkingSetSize; 00113 display_information -> _page_file_usage = process_memory_counters.PagefileUsage; 00114 display_information -> _peak_page_file_usage = process_memory_counters.PeakPagefileUsage; 00115 } 00116 00117 CloseHandle(process); 00118 } 00119 } 00120 } 00121 00122 typedef union 00123 { 00124 PN_uint64 long_integer; 00125 } 00126 LONG_INTEGER; 00127 00128 PN_uint64 cpu_time_function (void) { 00129 #ifdef _WIN64 00130 return __rdtsc(); 00131 #else 00132 LONG_INTEGER long_integer; 00133 LONG_INTEGER *long_integer_pointer; 00134 00135 long_integer_pointer = &long_integer; 00136 00137 __asm 00138 { 00139 mov ebx,[long_integer_pointer] 00140 rdtsc 00141 mov [ebx + 0], eax 00142 mov [ebx + 4], edx 00143 } 00144 00145 return long_integer.long_integer; 00146 #endif 00147 } 00148 00149 typedef union 00150 { 00151 struct 00152 { 00153 union 00154 { 00155 struct 00156 { 00157 unsigned char al; 00158 unsigned char ah; 00159 }; 00160 unsigned int eax; 00161 }; 00162 unsigned int ebx; 00163 unsigned int ecx; 00164 unsigned int edx; 00165 }; 00166 } 00167 CPU_ID_REGISTERS; 00168 00169 typedef struct 00170 { 00171 union 00172 { 00173 struct 00174 { 00175 int maximum_cpu_id_input; 00176 char cpu_vendor [16]; 00177 }; 00178 00179 CPU_ID_REGISTERS cpu_id_registers_0; 00180 }; 00181 00182 union 00183 { 00184 CPU_ID_REGISTERS cpu_id_registers_1; 00185 00186 struct 00187 { 00188 // eax 00189 union 00190 { 00191 unsigned int eax; 00192 unsigned int version_information; 00193 struct 00194 { 00195 unsigned int stepping_id : 4; 00196 unsigned int model : 4; 00197 unsigned int family : 4; 00198 unsigned int processor_type : 2; 00199 unsigned int reserved_0 : 2; 00200 unsigned int extended_model_id : 4; 00201 unsigned int extended_family_id : 8; 00202 unsigned int reserved_1 : 4; 00203 }; 00204 }; 00205 00206 // ebx 00207 union 00208 { 00209 unsigned int ebx; 00210 struct 00211 { 00212 unsigned int brand_index : 8; 00213 unsigned int clflush : 8; 00214 unsigned int maximum_logical_processors : 8; 00215 unsigned int initial_apic_id : 8; 00216 }; 00217 }; 00218 00219 // ecx 00220 union 00221 { 00222 unsigned int ecx; 00223 struct 00224 { 00225 unsigned int sse3 : 1; 00226 unsigned int reserved_1_to_2 : 2; 00227 unsigned int monitor : 1; 00228 unsigned int ds_cpl : 1; 00229 unsigned int vmx : 1; 00230 unsigned int reserved_6 : 1; 00231 unsigned int est : 1; 00232 unsigned int tm2 : 1; 00233 unsigned int reserved_9 : 1; 00234 unsigned int cnxt_id : 1; 00235 unsigned int reserved_11_to_12 : 2; 00236 unsigned int cmpxchg16b : 1; 00237 unsigned int xtpr_disable : 1; 00238 unsigned int reserved_15_to_31 : 17; 00239 }; 00240 }; 00241 00242 // edx 00243 union 00244 { 00245 unsigned int edx; 00246 struct 00247 { 00248 unsigned int fpu : 1; 00249 unsigned int vme : 1; 00250 unsigned int de : 1; 00251 unsigned int pse : 1; 00252 unsigned int tsc : 1; 00253 unsigned int msr : 1; 00254 unsigned int pae : 1; 00255 unsigned int mce : 1; 00256 unsigned int cx8 : 1; 00257 unsigned int apic : 1; 00258 unsigned int reserved_10 : 1; 00259 unsigned int sep : 1; 00260 unsigned int mtrr : 1; 00261 unsigned int pge : 1; 00262 unsigned int mca : 1; 00263 unsigned int cmov : 1; 00264 unsigned int pat : 1; 00265 unsigned int pse_36 : 1; 00266 unsigned int psn : 1; 00267 unsigned int cflush : 1; 00268 unsigned int reserved_20 : 1; 00269 unsigned int ds : 1; 00270 unsigned int acpi : 1; 00271 unsigned int mmx : 1; 00272 unsigned int fxsr : 1; 00273 unsigned int sse : 1; 00274 unsigned int sse2 : 1; 00275 unsigned int ss : 1; 00276 unsigned int htt : 1; 00277 unsigned int tm : 1; 00278 unsigned int reserved_30 : 1; 00279 unsigned int pbe : 1; 00280 }; 00281 }; 00282 }; 00283 }; 00284 00285 #define MAXIMUM_2 8 00286 #define MAXIMUM_CHARACTERS (MAXIMUM_2 * sizeof (CPU_ID_REGISTERS)) 00287 00288 union 00289 { 00290 CPU_ID_REGISTERS cpu_id_registers_2; 00291 unsigned char character_array_2 [MAXIMUM_CHARACTERS]; 00292 CPU_ID_REGISTERS cpu_id_registers_2_array [MAXIMUM_2]; 00293 }; 00294 00295 union 00296 { 00297 CPU_ID_REGISTERS cpu_id_registers_0x80000000; 00298 }; 00299 00300 union 00301 { 00302 CPU_ID_REGISTERS cpu_id_registers_0x80000001; 00303 }; 00304 00305 union 00306 { 00307 char cpu_brand_string [sizeof (CPU_ID_REGISTERS) * 3]; 00308 struct 00309 { 00310 CPU_ID_REGISTERS cpu_id_registers_0x80000002; 00311 CPU_ID_REGISTERS cpu_id_registers_0x80000003; 00312 CPU_ID_REGISTERS cpu_id_registers_0x80000004; 00313 }; 00314 }; 00315 00316 union 00317 { 00318 struct 00319 { 00320 // eax 00321 union 00322 { 00323 unsigned int eax; 00324 }; 00325 00326 // ebx 00327 union 00328 { 00329 unsigned int ebx; 00330 }; 00331 00332 // ecx 00333 union 00334 { 00335 unsigned int ecx; 00336 struct 00337 { 00338 unsigned int l1_data_cache_line_size : 8; 00339 unsigned int l1_data_reserved_8_to_15 : 8; 00340 unsigned int l1_data_associativity : 8; 00341 unsigned int l1_data_cache_size : 8; 00342 }; 00343 }; 00344 00345 // edx 00346 union 00347 { 00348 unsigned int edx; 00349 struct 00350 { 00351 unsigned int l1_code_cache_line_size : 8; 00352 unsigned int l1_code_reserved_8_to_15 : 8; 00353 unsigned int l1_code_associativity : 8; 00354 unsigned int l1_code_cache_size : 8; 00355 }; 00356 }; 00357 }; 00358 CPU_ID_REGISTERS cpu_id_registers_0x80000005; 00359 }; 00360 00361 union 00362 { 00363 struct 00364 { 00365 // eax 00366 union 00367 { 00368 unsigned int eax; 00369 }; 00370 00371 // ebx 00372 union 00373 { 00374 unsigned int ebx; 00375 }; 00376 00377 // ecx 00378 union 00379 { 00380 unsigned int ecx; 00381 struct 00382 { 00383 unsigned int l2_cache_line_size : 8; 00384 unsigned int l2_reserved_8_to_11 : 4; 00385 unsigned int l2_associativity : 4; 00386 unsigned int l2_cache_size : 16; 00387 }; 00388 }; 00389 00390 // edx 00391 union 00392 { 00393 unsigned int edx; 00394 }; 00395 }; 00396 CPU_ID_REGISTERS cpu_id_registers_0x80000006; 00397 }; 00398 00399 union 00400 { 00401 struct 00402 { 00403 // eax 00404 union 00405 { 00406 unsigned int eax; 00407 }; 00408 00409 // ebx 00410 union 00411 { 00412 unsigned int ebx; 00413 }; 00414 00415 // ecx 00416 union 00417 { 00418 unsigned int ecx; 00419 }; 00420 00421 // edx 00422 union 00423 { 00424 unsigned int edx; 00425 }; 00426 }; 00427 CPU_ID_REGISTERS cpu_id_registers_0x80000008; 00428 }; 00429 00430 unsigned int cache_line_size; 00431 unsigned int log_base_2_cache_line_size; 00432 } 00433 CPU_ID; 00434 00435 typedef struct 00436 { 00437 CPU_ID_REGISTERS cpu_id_registers_0; 00438 CPU_ID_REGISTERS cpu_id_registers_1; 00439 00440 CPU_ID_REGISTERS cpu_id_registers_0x80000000; 00441 CPU_ID_REGISTERS cpu_id_registers_0x80000001; 00442 CPU_ID_REGISTERS cpu_id_registers_0x80000002; 00443 CPU_ID_REGISTERS cpu_id_registers_0x80000003; 00444 CPU_ID_REGISTERS cpu_id_registers_0x80000004; 00445 00446 CPU_ID_REGISTERS cpu_id_registers_0x80000006; 00447 00448 CPU_ID_REGISTERS cpu_id_registers_0x80000008; 00449 } 00450 CPU_ID_BINARY_DATA; 00451 00452 typedef struct 00453 { 00454 union 00455 { 00456 CPU_ID_BINARY_DATA cpu_binary_data; 00457 unsigned int data_array [sizeof (CPU_ID_BINARY_DATA) / 4]; 00458 }; 00459 } 00460 CPU_ID_BINARY_DATA_ARRAY; 00461 00462 void cpu_id_to_cpu_id_binary_data (CPU_ID *cpu_id, CPU_ID_BINARY_DATA *cpu_id_binary_data) { 00463 00464 cpu_id_binary_data -> cpu_id_registers_0 = cpu_id -> cpu_id_registers_0; 00465 cpu_id_binary_data -> cpu_id_registers_1 = cpu_id -> cpu_id_registers_1; 00466 cpu_id_binary_data -> cpu_id_registers_0x80000000 = cpu_id -> cpu_id_registers_0x80000000; 00467 cpu_id_binary_data -> cpu_id_registers_0x80000001 = cpu_id -> cpu_id_registers_0x80000001; 00468 cpu_id_binary_data -> cpu_id_registers_0x80000002 = cpu_id -> cpu_id_registers_0x80000002; 00469 cpu_id_binary_data -> cpu_id_registers_0x80000003 = cpu_id -> cpu_id_registers_0x80000003; 00470 cpu_id_binary_data -> cpu_id_registers_0x80000004 = cpu_id -> cpu_id_registers_0x80000004; 00471 cpu_id_binary_data -> cpu_id_registers_0x80000006 = cpu_id -> cpu_id_registers_0x80000006; 00472 cpu_id_binary_data -> cpu_id_registers_0x80000008 = cpu_id -> cpu_id_registers_0x80000008; 00473 } 00474 00475 void cpu_id_binary_data_to_cpu_id (CPU_ID_BINARY_DATA *cpu_id_binary_data, CPU_ID *cpu_id) { 00476 00477 memset (cpu_id, 0, sizeof (CPU_ID)); 00478 00479 cpu_id -> cpu_id_registers_0 = cpu_id_binary_data -> cpu_id_registers_0; 00480 cpu_id -> cpu_id_registers_1 = cpu_id_binary_data -> cpu_id_registers_1; 00481 cpu_id -> cpu_id_registers_0x80000000 = cpu_id_binary_data -> cpu_id_registers_0x80000000; 00482 cpu_id -> cpu_id_registers_0x80000001 = cpu_id_binary_data -> cpu_id_registers_0x80000001; 00483 cpu_id -> cpu_id_registers_0x80000002 = cpu_id_binary_data -> cpu_id_registers_0x80000002; 00484 cpu_id -> cpu_id_registers_0x80000003 = cpu_id_binary_data -> cpu_id_registers_0x80000003; 00485 cpu_id -> cpu_id_registers_0x80000004 = cpu_id_binary_data -> cpu_id_registers_0x80000004; 00486 cpu_id -> cpu_id_registers_0x80000006 = cpu_id_binary_data -> cpu_id_registers_0x80000006; 00487 cpu_id -> cpu_id_registers_0x80000008 = cpu_id_binary_data -> cpu_id_registers_0x80000008; 00488 } 00489 00490 int cpuid (int input_eax, CPU_ID_REGISTERS *cpu_id_registers) { 00491 int state; 00492 00493 state = false; 00494 __try 00495 { 00496 if (input_eax == 0) { 00497 // the order of ecx and edx is swapped when saved to make a proper vendor string 00498 #ifdef _WIN64 00499 __cpuid((int*)cpu_id_registers, input_eax); 00500 unsigned int tmp = cpu_id_registers->edx; 00501 cpu_id_registers->edx = cpu_id_registers->ecx; 00502 cpu_id_registers->ecx = tmp; 00503 #else 00504 __asm 00505 { 00506 mov eax, [input_eax] 00507 mov edi, [cpu_id_registers] 00508 00509 cpuid 00510 00511 mov [edi + 0], eax 00512 mov [edi + 4], ebx 00513 mov [edi + 8], edx 00514 mov [edi + 12], ecx 00515 } 00516 #endif 00517 } 00518 else { 00519 #ifdef _WIN64 00520 __cpuid((int*)cpu_id_registers, input_eax); 00521 #else 00522 __asm 00523 { 00524 mov eax, [input_eax] 00525 mov edi, [cpu_id_registers] 00526 00527 cpuid 00528 00529 mov [edi + 0], eax 00530 mov [edi + 4], ebx 00531 mov [edi + 8], ecx 00532 mov [edi + 12], edx 00533 } 00534 #endif 00535 } 00536 00537 state = true; 00538 } 00539 __except (1) 00540 { 00541 state = false; 00542 } 00543 00544 return state; 00545 } 00546 00547 void parse_cpu_id (CPU_ID *cpu_id) { 00548 00549 printf ("CPUID\n"); 00550 printf (" vendor = %s \n", cpu_id -> cpu_vendor); 00551 printf (" brand string %s \n", cpu_id -> cpu_brand_string); 00552 printf (" maximum_cpu_id_input = %u \n", cpu_id -> maximum_cpu_id_input); 00553 printf (" maximum extended information = 0x%X \n", cpu_id -> cpu_id_registers_0x80000000.eax); 00554 00555 printf (" MMX = %u \n", cpu_id -> mmx); 00556 printf (" SSE = %u \n", cpu_id -> sse); 00557 printf (" SSE2 = %u \n", cpu_id -> sse2); 00558 printf (" SSE3 = %u \n", cpu_id -> sse3); 00559 00560 printf (" EST = %u \n", cpu_id -> est); 00561 00562 if (cpu_id -> maximum_cpu_id_input >= 1) { 00563 printf (" version_information \n"); 00564 printf (" stepping_id %u \n", cpu_id -> stepping_id); 00565 printf (" model %u \n", cpu_id -> model); 00566 printf (" family %u \n", cpu_id -> family); 00567 printf (" processor_type %u \n", cpu_id -> processor_type); 00568 printf (" extended_model_id %u \n", cpu_id -> extended_model_id); 00569 printf (" extended_family_id %u \n", cpu_id -> extended_family_id); 00570 00571 printf (" brand_index %u \n", cpu_id -> brand_index); 00572 printf (" clflush %u \n", cpu_id -> clflush); 00573 printf (" maximum_logical_processors %u \n", cpu_id -> maximum_logical_processors); 00574 printf (" initial_apic_id %u \n", cpu_id -> initial_apic_id); 00575 00576 // printf (" cache_line_size %u \n", cpu_id -> cache_line_size); 00577 // printf (" log_base_2_cache_line_size %u \n", cpu_id -> log_base_2_cache_line_size); 00578 } 00579 00580 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000005) { 00581 printf (" l1_data_cache_line_size %d \n", cpu_id -> l1_data_cache_line_size); 00582 printf (" l1_data_associativity %d \n", cpu_id -> l1_data_associativity); 00583 printf (" l1_data_cache_size %dK \n", cpu_id -> l1_data_cache_size); 00584 00585 printf (" l1_code_cache_line_size %d \n", cpu_id -> l1_code_cache_line_size); 00586 printf (" l1_code_associativity %d \n", cpu_id -> l1_code_associativity); 00587 printf (" l1_code_cache_size %dK \n", cpu_id -> l1_code_cache_size); 00588 } 00589 00590 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000006) { 00591 printf (" l2_cache_line_size %d \n", cpu_id -> l2_cache_line_size); 00592 printf (" l2_associativity %d \n", cpu_id -> l2_associativity); 00593 printf (" l2_cache_size %dK \n", cpu_id -> l2_cache_size); 00594 } 00595 } 00596 00597 int initialize_cpu_id (CPU_ID *cpu_id) { 00598 00599 int state; 00600 int debug; 00601 00602 state = false; 00603 debug = false; 00604 memset (cpu_id, 0, sizeof (CPU_ID)); 00605 00606 if (cpuid (0, &cpu_id -> cpu_id_registers_0)) { 00607 if (cpu_id -> maximum_cpu_id_input >= 1) { 00608 cpuid (1, &cpu_id -> cpu_id_registers_1); 00609 } 00610 if (cpu_id -> maximum_cpu_id_input >= 2) { 00611 unsigned int index; 00612 00613 cpuid (2, &cpu_id -> cpu_id_registers_2); 00614 if (debug) { 00615 printf (" al = %u \n", cpu_id -> cpu_id_registers_2.al); 00616 } 00617 00618 for (index = 1; index < cpu_id -> cpu_id_registers_2.al && index < MAXIMUM_2; index++) { 00619 cpuid (2, &cpu_id -> cpu_id_registers_2_array [index]); 00620 } 00621 00622 for (index = 1; index < MAXIMUM_CHARACTERS; index++) { 00623 if (cpu_id -> character_array_2 [index]) { 00624 if (debug) { 00625 printf (" cache/TLB byte = %X \n", cpu_id -> character_array_2 [index]); 00626 } 00627 switch (cpu_id -> character_array_2 [index]) 00628 { 00629 case 0x0A: 00630 case 0x0C: 00631 cpu_id -> cache_line_size = 32; 00632 cpu_id -> log_base_2_cache_line_size = 5; 00633 break; 00634 00635 case 0x2C: 00636 case 0x60: 00637 case 0x66: 00638 case 0x67: 00639 case 0x68: 00640 cpu_id -> cache_line_size = 64; 00641 cpu_id -> log_base_2_cache_line_size = 6; 00642 break; 00643 } 00644 } 00645 } 00646 } 00647 00648 cpuid (0x80000000, &cpu_id -> cpu_id_registers_0x80000000); 00649 00650 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000001) { 00651 cpuid (0x80000001, &cpu_id -> cpu_id_registers_0x80000001); 00652 } 00653 00654 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000004) { 00655 cpuid (0x80000002, &cpu_id -> cpu_id_registers_0x80000002); 00656 cpuid (0x80000003, &cpu_id -> cpu_id_registers_0x80000003); 00657 cpuid (0x80000004, &cpu_id -> cpu_id_registers_0x80000004); 00658 } 00659 00660 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000005) { 00661 cpuid (0x80000005, &cpu_id -> cpu_id_registers_0x80000005); 00662 } 00663 00664 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000006) { 00665 cpuid (0x80000006, &cpu_id -> cpu_id_registers_0x80000006); 00666 } 00667 00668 if (cpu_id -> cpu_id_registers_0x80000000.eax >= 0x80000008) { 00669 cpuid (0x80000008, &cpu_id -> cpu_id_registers_0x80000008); 00670 } 00671 00672 state = true; 00673 } 00674 00675 return state; 00676 } 00677 00678 int update_cpu_frequency_function (int processor_number, DisplayInformation *display_information) 00679 { 00680 int update; 00681 00682 update = false; 00683 display_information -> _maximum_cpu_frequency = 0; 00684 display_information -> _current_cpu_frequency = 0; 00685 00686 if (CallNtPowerInformationFunction) { 00687 00688 int i; 00689 PVOID input_buffer; 00690 PVOID output_buffer; 00691 ULONG input_buffer_size; 00692 ULONG output_buffer_size; 00693 POWER_INFORMATION_LEVEL information_level; 00694 PROCESSOR_POWER_INFORMATION *processor_power_information; 00695 PROCESSOR_POWER_INFORMATION processor_power_information_array [MAXIMUM_PROCESSORS]; 00696 00697 memset (processor_power_information_array, 0, sizeof (PROCESSOR_POWER_INFORMATION) * MAXIMUM_PROCESSORS); 00698 00699 processor_power_information = processor_power_information_array; 00700 for (i = 0; i < MAXIMUM_PROCESSORS; i++) { 00701 processor_power_information -> Number = 0xFFFFFFFF; 00702 processor_power_information++; 00703 } 00704 00705 information_level = ProcessorInformation; 00706 input_buffer = NULL; 00707 output_buffer = processor_power_information_array; 00708 input_buffer_size = 0; 00709 output_buffer_size = sizeof (PROCESSOR_POWER_INFORMATION) * MAXIMUM_PROCESSORS; 00710 if (CallNtPowerInformationFunction (information_level, input_buffer, input_buffer_size, output_buffer, output_buffer_size) == 0) { 00711 processor_power_information = processor_power_information_array; 00712 for (i = 0; i < MAXIMUM_PROCESSORS; i++) { 00713 if (processor_power_information -> Number == processor_number) { 00714 PN_uint64 value; 00715 00716 value = processor_power_information -> MaxMhz; 00717 display_information -> _maximum_cpu_frequency = value * 1000000; 00718 00719 value = processor_power_information -> CurrentMhz; 00720 display_information -> _current_cpu_frequency = value * 1000000; 00721 update = true; 00722 00723 break; 00724 } 00725 00726 processor_power_information++; 00727 } 00728 } 00729 } 00730 00731 return update; 00732 } 00733 00734 void 00735 count_number_of_cpus(DisplayInformation *display_information) { 00736 int num_cpu_cores = 0; 00737 int num_logical_cpus = 0; 00738 00739 // Get a pointer to the GetLogicalProcessorInformation function. 00740 typedef BOOL (WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, 00741 PDWORD); 00742 LPFN_GLPI glpi; 00743 glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), 00744 "GetLogicalProcessorInformation"); 00745 if (glpi == NULL) { 00746 windisplay_cat.info() 00747 << "GetLogicalProcessorInformation is not supported.\n"; 00748 return; 00749 } 00750 00751 // Allocate a buffer to hold the result of the 00752 // GetLogicalProcessorInformation call. 00753 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; 00754 DWORD buffer_length = 0; 00755 DWORD rc = glpi(buffer, &buffer_length); 00756 while (!rc) { 00757 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { 00758 if (buffer != NULL) { 00759 PANDA_FREE_ARRAY(buffer); 00760 } 00761 00762 buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)PANDA_MALLOC_ARRAY(buffer_length); 00763 nassertv(buffer != NULL); 00764 } else { 00765 windisplay_cat.info() 00766 << "GetLogicalProcessorInformation failed: " << GetLastError() 00767 << "\n"; 00768 return; 00769 } 00770 rc = glpi(buffer, &buffer_length); 00771 } 00772 00773 // Now get the results. 00774 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = buffer; 00775 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION end = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)((char *)buffer + buffer_length); 00776 00777 while (ptr < end) { 00778 if (ptr->Relationship == RelationProcessorCore) { 00779 num_cpu_cores++; 00780 00781 // A hyperthreaded core supplies more than one logical processor. 00782 num_logical_cpus += count_bits_in_word((PN_uint64)(ptr->ProcessorMask)); 00783 } 00784 ++ptr; 00785 } 00786 00787 PANDA_FREE_ARRAY(buffer); 00788 00789 windisplay_cat.info() 00790 << num_cpu_cores << " CPU cores, with " 00791 << num_logical_cpus << " logical processors.\n"; 00792 00793 display_information->_num_cpu_cores = num_cpu_cores; 00794 display_information->_num_logical_cpus = num_logical_cpus; 00795 } 00796 00797 00798 //////////////////////////////////////////////////////////////////// 00799 // Function: WinGraphicsPipe::Constructor 00800 // Access: Public 00801 // Description: 00802 //////////////////////////////////////////////////////////////////// 00803 WinGraphicsPipe:: 00804 WinGraphicsPipe() { 00805 00806 bool state; 00807 char string [512]; 00808 00809 state = false; 00810 _supported_types = OT_window | OT_fullscreen_window; 00811 00812 // these fns arent defined on win95, so get dynamic ptrs to them 00813 // to avoid ugly DLL loader failures on w95 00814 _pfnTrackMouseEvent = NULL; 00815 00816 _hUser32 = (HINSTANCE)LoadLibrary("user32.dll"); 00817 if (_hUser32 != NULL) { 00818 _pfnTrackMouseEvent = 00819 (PFN_TRACKMOUSEEVENT)GetProcAddress(_hUser32, "TrackMouseEvent"); 00820 } 00821 00822 #ifdef HAVE_DX9 00823 if (request_dxdisplay_information){ 00824 DisplaySearchParameters display_search_parameters_dx9; 00825 int dx9_display_information (DisplaySearchParameters &display_search_parameters_dx9, DisplayInformation *display_information); 00826 00827 if (state == false && dx9_display_information (display_search_parameters_dx9, _display_information)) { 00828 state = true; 00829 } 00830 } 00831 #endif 00832 00833 #ifdef HAVE_DX8 00834 if (request_dxdisplay_information){ 00835 DisplaySearchParameters display_search_parameters_dx8; 00836 int dx8_display_information (DisplaySearchParameters &display_search_parameters_dx8, DisplayInformation *display_information); 00837 00838 if (state == false && dx8_display_information (display_search_parameters_dx8, _display_information)) { 00839 state = true; 00840 } 00841 } 00842 #endif 00843 00844 if (auto_cpu_data) { 00845 lookup_cpu_data(); 00846 } 00847 00848 OSVERSIONINFO version_info; 00849 00850 version_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 00851 if (GetVersionEx (&version_info)) { 00852 sprintf (string, "OS version: %d.%d.%d.%d \n", version_info.dwMajorVersion, version_info.dwMinorVersion, version_info.dwPlatformId, version_info.dwBuildNumber); 00853 windisplay_cat.info() << string; 00854 windisplay_cat.info() << " " << version_info.szCSDVersion << "\n"; 00855 00856 _display_information -> _os_version_major = version_info.dwMajorVersion; 00857 _display_information -> _os_version_minor = version_info.dwMinorVersion; 00858 _display_information -> _os_version_build = version_info.dwBuildNumber; 00859 _display_information -> _os_platform_id = version_info.dwPlatformId; 00860 } 00861 // Screen size 00862 _display_width = GetSystemMetrics(SM_CXSCREEN); 00863 _display_height = GetSystemMetrics(SM_CYSCREEN); 00864 00865 HMODULE power_dll; 00866 00867 power_dll = LoadLibrary ("PowrProf.dll"); 00868 if (power_dll) { 00869 CallNtPowerInformationFunction = (CallNtPowerInformationType) GetProcAddress (power_dll, "CallNtPowerInformation"); 00870 if (CallNtPowerInformationFunction) { 00871 00872 _display_information -> _update_cpu_frequency_function = update_cpu_frequency_function; 00873 update_cpu_frequency_function(0, _display_information); 00874 00875 sprintf (string, "max Mhz %I64d, current Mhz %I64d \n", _display_information -> _maximum_cpu_frequency, _display_information -> _current_cpu_frequency); 00876 00877 windisplay_cat.info() << string; 00878 } 00879 } 00880 00881 if (state) { 00882 00883 } 00884 } 00885 00886 //////////////////////////////////////////////////////////////////// 00887 // Function: WinGraphicsPipe::lookup_cpu_data 00888 // Access: Public, Virtual 00889 // Description: Looks up the detailed CPU information and stores it 00890 // in _display_information, if supported by the OS. 00891 // This may take a second or two. 00892 //////////////////////////////////////////////////////////////////// 00893 void WinGraphicsPipe:: 00894 lookup_cpu_data() { 00895 char string [512]; 00896 00897 // set callback for memory function 00898 _display_information -> _get_memory_information_function = get_memory_information; 00899 00900 // set callback for cpu time function 00901 _display_information -> _cpu_time_function = cpu_time_function; 00902 00903 // determine CPU frequency 00904 PN_uint64 time; 00905 PN_uint64 end_time; 00906 LARGE_INTEGER counter; 00907 LARGE_INTEGER end; 00908 LARGE_INTEGER frequency; 00909 00910 time = 0; 00911 end_time = 0; 00912 counter.QuadPart = 0; 00913 end.QuadPart = 0; 00914 frequency.QuadPart = 0; 00915 00916 int priority; 00917 HANDLE thread; 00918 00919 windisplay_cat.info() << "begin QueryPerformanceFrequency\n"; 00920 thread = GetCurrentThread(); 00921 priority = GetThreadPriority (thread); 00922 SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL); 00923 00924 if (QueryPerformanceFrequency(&frequency)) { 00925 if (frequency.QuadPart > 0) { 00926 if (QueryPerformanceCounter (&counter)) { 00927 time = cpu_time_function(); 00928 end.QuadPart = counter.QuadPart + frequency.QuadPart; 00929 while (QueryPerformanceCounter (&counter) && counter.QuadPart < end.QuadPart) { 00930 00931 } 00932 end_time = cpu_time_function(); 00933 00934 _display_information -> _cpu_frequency = end_time - time; 00935 } 00936 } 00937 } 00938 00939 SetThreadPriority(thread, priority); 00940 sprintf (string, "QueryPerformanceFrequency: %I64d\n", frequency.QuadPart); 00941 windisplay_cat.info() << string; 00942 sprintf (string, "CPU frequency: %I64d\n", _display_information -> _cpu_frequency); 00943 windisplay_cat.info() << string; 00944 00945 00946 // CPUID 00947 CPU_ID cpu_id; 00948 00949 windisplay_cat.info() << "start CPU ID\n"; 00950 00951 if (initialize_cpu_id (&cpu_id)) { 00952 CPU_ID_BINARY_DATA *cpu_id_binary_data; 00953 00954 cpu_id_binary_data = new (CPU_ID_BINARY_DATA); 00955 if (cpu_id_binary_data) { 00956 cpu_id_to_cpu_id_binary_data (&cpu_id, cpu_id_binary_data); 00957 _display_information -> _cpu_id_size = sizeof (CPU_ID_BINARY_DATA) / sizeof (unsigned int); 00958 _display_information -> _cpu_id_data = (unsigned int *) cpu_id_binary_data; 00959 00960 _display_information -> _cpu_vendor_string = strdup(cpu_id.cpu_vendor); 00961 _display_information -> _cpu_brand_string = strdup(cpu_id.cpu_brand_string); 00962 _display_information -> _cpu_version_information = cpu_id.version_information; 00963 _display_information -> _cpu_brand_index = cpu_id.brand_index; 00964 00965 if (windisplay_cat.is_debug()) { 00966 windisplay_cat.debug() 00967 << hex << _display_information -> _cpu_id_version << dec << "|"; 00968 00969 int index; 00970 for (index = 0; index < _display_information -> _cpu_id_size; index++) { 00971 unsigned int data; 00972 00973 data = _display_information -> _cpu_id_data [index]; 00974 00975 windisplay_cat.debug(false) 00976 << hex << data << dec; 00977 if (index < (_display_information -> _cpu_id_size - 1)) { 00978 windisplay_cat.debug(false) 00979 << "|"; 00980 } 00981 } 00982 windisplay_cat.debug(false) 00983 << "\n"; 00984 } 00985 } 00986 00987 if (windisplay_cat.is_debug()) { 00988 parse_cpu_id (&cpu_id); 00989 } 00990 } 00991 00992 windisplay_cat.info() << "end CPU ID\n"; 00993 00994 // Number of CPU's 00995 count_number_of_cpus(_display_information); 00996 } 00997 00998 //////////////////////////////////////////////////////////////////// 00999 // Function: WinGraphicsPipe::Destructor 01000 // Access: Public, Virtual 01001 // Description: 01002 //////////////////////////////////////////////////////////////////// 01003 WinGraphicsPipe:: 01004 ~WinGraphicsPipe() { 01005 if (_hUser32 != NULL) { 01006 FreeLibrary(_hUser32); 01007 _hUser32 = NULL; 01008 } 01009 } 01010 01011 bool MyGetProcAddr(HINSTANCE hDLL, FARPROC *pFn, const char *szExportedFnName) { 01012 *pFn = (FARPROC) GetProcAddress(hDLL, szExportedFnName); 01013 if (*pFn == NULL) { 01014 windisplay_cat.error() << "GetProcAddr failed for " << szExportedFnName << ", error=" << GetLastError() <<endl; 01015 return false; 01016 } 01017 return true; 01018 } 01019 01020 bool MyLoadLib(HINSTANCE &hDLL, const char *DLLname) { 01021 hDLL = LoadLibrary(DLLname); 01022 if(hDLL == NULL) { 01023 windisplay_cat.error() << "LoadLibrary failed for " << DLLname << ", error=" << GetLastError() <<endl; 01024 return false; 01025 } 01026 return true; 01027 }