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