Panda3D

winGraphicsPipe.cxx

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 }
 All Classes Functions Variables Enumerations