Hardware/Nvidia/NVAPI.cs
author moel.mich
Tue, 18 May 2010 19:16:55 +0000
changeset 121 f7e492b43690
parent 101 f8589379e32c
child 140 04a5155c9c1a
permissions -rw-r--r--
Fixed an EntryPointNotFoundException in the NVAPI wrapper:

System.EntryPointNotFoundException: N?o ? poss?vel localizar um ponto de entrada denominado 'nvapi_QueryInterface' na DLL 'nvapi.dll'.
em PInvokeDelegateFactoryInternalWrapperType38.nvapi_QueryInterface(UInt32 id)
em OpenHardwareMonitor.Hardware.Nvidia.NVAPI.GetDelegate[T](UInt32 id, T& newDelegate)
em OpenHardwareMonitor.Hardware.Nvidia.NVAPI..cctor()
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.Runtime.InteropServices;
    41 using System.Text;
    42 
    43 namespace OpenHardwareMonitor.Hardware.Nvidia {
    44 
    45   public enum NvStatus {
    46     OK = 0,
    47     ERROR = -1,
    48     LIBRARY_NOT_FOUND = -2,
    49     NO_IMPLEMENTATION = -3,
    50     API_NOT_INTIALIZED = -4,
    51     INVALID_ARGUMENT = -5,
    52     NVIDIA_DEVICE_NOT_FOUND = -6,
    53     END_ENUMERATION = -7,
    54     INVALID_HANDLE = -8,
    55     INCOMPATIBLE_STRUCT_VERSION = -9,
    56     HANDLE_INVALIDATED = -10,
    57     OPENGL_CONTEXT_NOT_CURRENT = -11,
    58     NO_GL_EXPERT = -12,
    59     INSTRUMENTATION_DISABLED = -13,
    60     EXPECTED_LOGICAL_GPU_HANDLE = -100,
    61     EXPECTED_PHYSICAL_GPU_HANDLE = -101,
    62     EXPECTED_DISPLAY_HANDLE = -102,
    63     INVALID_COMBINATION = -103,
    64     NOT_SUPPORTED = -104,
    65     PORTID_NOT_FOUND = -105,
    66     EXPECTED_UNATTACHED_DISPLAY_HANDLE = -106,
    67     INVALID_PERF_LEVEL = -107,
    68     DEVICE_BUSY = -108,
    69     NV_PERSIST_FILE_NOT_FOUND = -109,
    70     PERSIST_DATA_NOT_FOUND = -110,
    71     EXPECTED_TV_DISPLAY = -111,
    72     EXPECTED_TV_DISPLAY_ON_DCONNECTOR = -112,
    73     NO_ACTIVE_SLI_TOPOLOGY = -113,
    74     SLI_RENDERING_MODE_NOTALLOWED = -114,
    75     EXPECTED_DIGITAL_FLAT_PANEL = -115,
    76     ARGUMENT_EXCEED_MAX_SIZE = -116,
    77     DEVICE_SWITCHING_NOT_ALLOWED = -117,
    78     TESTING_CLOCKS_NOT_SUPPORTED = -118,
    79     UNKNOWN_UNDERSCAN_CONFIG = -119,
    80     TIMEOUT_RECONFIGURING_GPU_TOPO = -120,
    81     DATA_NOT_FOUND = -121,
    82     EXPECTED_ANALOG_DISPLAY = -122,
    83     NO_VIDLINK = -123,
    84     REQUIRES_REBOOT = -124,
    85     INVALID_HYBRID_MODE = -125,
    86     MIXED_TARGET_TYPES = -126,
    87     SYSWOW64_NOT_SUPPORTED = -127,
    88     IMPLICIT_SET_GPU_TOPOLOGY_CHANGE_NOT_ALLOWED = -128,
    89     REQUEST_USER_TO_CLOSE_NON_MIGRATABLE_APPS = -129,
    90     OUT_OF_MEMORY = -130,
    91     WAS_STILL_DRAWING = -131,
    92     FILE_NOT_FOUND = -132,
    93     TOO_MANY_UNIQUE_STATE_OBJECTS = -133,
    94     INVALID_CALL = -134,
    95     D3D10_1_LIBRARY_NOT_FOUND = -135,
    96     FUNCTION_NOT_FOUND = -136
    97   }  
    98 
    99   public enum NvThermalController {
   100     NONE = 0,
   101     GPU_INTERNAL,  
   102     ADM1032,
   103     MAX6649,       
   104     MAX1617,      
   105     LM99,      
   106     LM89,         
   107     LM64,         
   108     ADT7473,
   109     SBMAX6649,
   110     VBIOSEVT,  
   111     OS,    
   112     UNKNOWN = -1,
   113   } 
   114 
   115   public enum NvThermalTarget {
   116     NONE = 0,
   117     GPU = 1,
   118     MEMORY = 2,
   119     POWER_SUPPLY = 4,
   120     BOARD = 8,
   121     ALL = 15,
   122     UNKNOWN = -1
   123   };
   124 
   125   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   126   public struct NvSensor {
   127     public NvThermalController Controller;
   128     public int DefaultMinTemp;
   129     public int DefaultMaxTemp;
   130     public int CurrentTemp;
   131     public NvThermalTarget Target;     
   132   }
   133 
   134   [StructLayout(LayoutKind.Sequential, Pack = 8)]
   135   public struct NvGPUThermalSettings {
   136     public int Version;
   137     public int Count;
   138     [MarshalAs(UnmanagedType.ByValArray, 
   139       SizeConst = NVAPI.MAX_THERMAL_SENSORS_PER_GPU)]
   140     public NvSensor[] Sensor;
   141   }
   142 
   143   [StructLayout(LayoutKind.Sequential)]
   144   public struct NvDisplayHandle {
   145     private IntPtr ptr;
   146   }
   147 
   148   [StructLayout(LayoutKind.Sequential)]
   149   public struct NvPhysicalGpuHandle {
   150     private IntPtr ptr;
   151   }
   152 
   153   public class NVAPI {
   154           
   155     private const int SHORT_STRING_MAX = 64;
   156 
   157     public const int MAX_THERMAL_SENSORS_PER_GPU = 3;
   158     public const int MAX_PHYSICAL_GPUS = 64;
   159     public static readonly int GPU_THERMAL_SETTINGS_VER =
   160       Marshal.SizeOf(typeof(NvGPUThermalSettings)) | 0x10000;
   161             
   162     private delegate IntPtr nvapi_QueryInterfaceDelegate(uint id);
   163     private delegate NvStatus NvAPI_InitializeDelegate();
   164     private delegate NvStatus NvAPI_GPU_GetFullNameDelegate(
   165       NvPhysicalGpuHandle gpuHandle, StringBuilder name);
   166 
   167     public delegate NvStatus NvAPI_GPU_GetThermalSettingsDelegate(
   168       NvPhysicalGpuHandle gpuHandle, int sensorIndex, 
   169       ref NvGPUThermalSettings nvGPUThermalSettings);
   170     public delegate NvStatus NvAPI_EnumNvidiaDisplayHandleDelegate(int thisEnum,
   171       ref NvDisplayHandle displayHandle);
   172     public delegate NvStatus NvAPI_GetPhysicalGPUsFromDisplayDelegate(
   173       NvDisplayHandle displayHandle, [Out] NvPhysicalGpuHandle[] gpuHandles, 
   174       out int gpuCount);
   175     public delegate NvStatus NvAPI_EnumPhysicalGPUsDelegate(
   176       [Out] NvPhysicalGpuHandle[] gpuHandles, out int gpuCount);
   177     public delegate NvStatus NvAPI_GPU_GetTachReadingDelegate(
   178       NvPhysicalGpuHandle gpuHandle, out int value);
   179 
   180     private static bool available = false;
   181     private static nvapi_QueryInterfaceDelegate nvapi_QueryInterface;
   182     private static NvAPI_InitializeDelegate NvAPI_Initialize;
   183     private static NvAPI_GPU_GetFullNameDelegate _NvAPI_GPU_GetFullName;
   184 
   185     public static NvAPI_GPU_GetThermalSettingsDelegate 
   186       NvAPI_GPU_GetThermalSettings;
   187     public static NvAPI_EnumNvidiaDisplayHandleDelegate
   188       NvAPI_EnumNvidiaDisplayHandle;
   189     public static NvAPI_GetPhysicalGPUsFromDisplayDelegate
   190       NvAPI_GetPhysicalGPUsFromDisplay;
   191     public static NvAPI_EnumPhysicalGPUsDelegate
   192       NvAPI_EnumPhysicalGPUs;
   193     public static NvAPI_GPU_GetTachReadingDelegate
   194       NvAPI_GPU_GetTachReading;
   195 
   196     public static NvStatus NvAPI_GPU_GetFullName(NvPhysicalGpuHandle gpuHandle,
   197       out string name) {
   198       StringBuilder builder = new StringBuilder(SHORT_STRING_MAX);
   199       NvStatus status;
   200       if (_NvAPI_GPU_GetFullName != null)
   201         status = _NvAPI_GPU_GetFullName(gpuHandle, builder);
   202       else
   203         status = NvStatus.FUNCTION_NOT_FOUND;
   204       name = builder.ToString();
   205       return status;
   206     }
   207 
   208     private static string GetDllName() {
   209       if (IntPtr.Size == 4) {
   210         return "nvapi.dll";
   211       } else {
   212         return "nvapi64.dll";
   213       }
   214     }
   215 
   216     private static void GetDelegate<T>(uint id, out T newDelegate) 
   217       where T : class 
   218     {
   219       IntPtr ptr = nvapi_QueryInterface(id);
   220       if (ptr != IntPtr.Zero) {
   221         newDelegate =
   222           Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T;
   223       } else {
   224         newDelegate = null;
   225       }
   226     }
   227 
   228     static NVAPI() { 
   229       DllImportAttribute attribute = new DllImportAttribute(GetDllName());
   230       attribute.CallingConvention = CallingConvention.Cdecl;
   231       attribute.PreserveSig = true;
   232       attribute.EntryPoint = "nvapi_QueryInterface";
   233       PInvokeDelegateFactory.CreateDelegate(attribute,
   234         out nvapi_QueryInterface);
   235 
   236       try {
   237         GetDelegate(0x0150E828, out NvAPI_Initialize);
   238       } catch (DllNotFoundException) { return; } 
   239         catch (EntryPointNotFoundException) { return; } 
   240         catch (ArgumentNullException) { return; }
   241 
   242       if (NvAPI_Initialize() == NvStatus.OK) {
   243         GetDelegate(0xE3640A56, out NvAPI_GPU_GetThermalSettings);
   244         GetDelegate(0xCEEE8E9F, out _NvAPI_GPU_GetFullName);
   245         GetDelegate(0x9ABDD40D, out NvAPI_EnumNvidiaDisplayHandle);
   246         GetDelegate(0x34EF9506, out NvAPI_GetPhysicalGPUsFromDisplay);
   247         GetDelegate(0xE5AC921F, out NvAPI_EnumPhysicalGPUs);
   248         GetDelegate(0x5F608315, out NvAPI_GPU_GetTachReading);        
   249         available = true;
   250       }
   251     }
   252 
   253     public static bool IsAvailable {
   254       get { return available; }
   255     }
   256 
   257   }
   258 }