Publish LumaOps source

This commit is contained in:
LumaOps release export
2026-09-03 01:18:36 +02:00
commit 7f1c0e5f71
2363 changed files with 501543 additions and 0 deletions
@@ -0,0 +1,132 @@
/*---------------------------------------------------------*\
| NVIDIAIlluminationControllerDetect_Windows_Linux.cpp |
| |
| Detector for NVIDIA Illumination GPU |
| |
| Carter Miller (GingerRunner) 04 Jan 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "Detector.h"
#include "LogManager.h"
#include "RGBController_NVIDIAIllumination_Windows_Linux.h"
#include "pci_ids.h"
enum
{
NVIDIA_ILLUMINATION_V1
};
typedef struct
{
int pci_vendor;
int pci_device;
int pci_subsystem_vendor;
int pci_subsystem_device;
int gpu_rgb_version;
bool treats_rgbw_as_rgb;
const char * name;
} nv_gpu_pci_device;
#define GPU_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ]))
/*-----------------------------------------------------------------------------------------------------*\
| Certain devices seem to ignore the white value entirely, despite the zone being reported back by the |
| API as RGBW, so this boolean is passed at detection time via constructor inform the controller logic. |
\*-----------------------------------------------------------------------------------------------------*/
#define TREATS_RGBW_AS_RGB true
#define TREATS_RGBW_AS_RGBW false
static const nv_gpu_pci_device device_list[] =
{
{NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU104_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "Palit GeForce RTX 2060" },
{NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2060 FE" },
{NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2060 SUPER FE" },
{NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2070 FE" },
{NVIDIA_VEN, NVIDIA_RTX2070S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070_FE_SUPER_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2070 SUPER FE" },
{NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 FE" },
{NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 SUPER FE" },
{NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 Ti FE" },
{NVIDIA_VEN, NVIDIA_TITANRTX_DEV, NVIDIA_SUB_VEN, NVIDIA_TITANRTX_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA TITAN RTX" },
{NVIDIA_VEN, NVIDIA_RTX3050_DEV, NVIDIA_SUB_VEN, GAINWARD_RTX3050_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3050 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3060 Pegasus" },
{NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 Ti XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 Ti XLR8 REVEL EPIC-X" },
{NVIDIA_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "NVIDIA GeForce RTX 3060 Ti V1 LHR" },
{NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "NVIDIA GeForce RTX 3060 Ti LHR" },
{NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PNY_SUB_VEN, PNY_RTX_3070TI_XLR8_UPRISING_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "PNY GeForce RTX 3070 Ti XLR8 Uprising EPIC-X"},
{NVIDIA_VEN, NVIDIA_RTX3080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3080 FE" },
{NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3080 Ti FE" },
{NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_SUB_VEN, MANLI_RTX3080TI_GALLARDO_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "MANLI GeForce RTX 3080 Ti GALLARDO" },
{NVIDIA_VEN, NVIDIA_RTX3090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3090 FE" },
{NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3090TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3090 Ti FE" },
{NVIDIA_VEN, NVIDIA_RTX4060_DEV, PALIT_SUB_VEN, PALIT_RTX4060_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4060 Dual" },
{NVIDIA_VEN, NVIDIA_RTX4070_DEV, PALIT_SUB_VEN, PALIT_RTX4070_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4070" },
{NVIDIA_VEN, NVIDIA_RTX4070S_DEV, PALIT_SUB_VEN, PALIT_RTX4070S_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4070 SUPER Dual" },
{NVIDIA_VEN, NVIDIA_RTX4070_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4070_GHOST_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "Gainward GeForce RTX 4070 Ghost" },
{NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 FE" },
{NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 FE" },
{NVIDIA_VEN, NVIDIA_RTX4080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 SUPER FE" },
{NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" },
{NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" },
{NVIDIA_VEN, NVIDIA_RTX5080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5080 FE" },
{NVIDIA_VEN, NVIDIA_RTX5090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5090 FE" },
};
void DetectNVIDIAIllumGPUs()
{
static NV_PHYSICAL_GPU_HANDLE gpu_handles[64];
static NV_S32 gpu_count = 0;
NV_U32 device_id;
NV_U32 ext_device_id;
NV_STATUS res;
NV_U32 revision_id;
NV_U32 sub_system_id;
NvAPI_Initialize();
NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count);
for(NV_S32 gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++)
{
res = NvAPI_GPU_GetPCIIdentifiers(gpu_handles[gpu_idx], &device_id, &sub_system_id, &revision_id, &ext_device_id);
if (res == 0)
{
uint16_t pci_device = device_id >> 16;
uint16_t pci_vendor = device_id & 0xffff;
uint16_t pci_subsystem_device = sub_system_id >> 16;
uint16_t pci_subsystem_vendor = sub_system_id & 0xffff;
for(unsigned int dev_idx = 0; dev_idx < GPU_NUM_DEVICES; dev_idx++)
{
if(pci_vendor == device_list[dev_idx].pci_vendor &&
pci_device == device_list[dev_idx].pci_device &&
pci_subsystem_vendor == device_list[dev_idx].pci_subsystem_vendor &&
pci_subsystem_device == device_list[dev_idx].pci_subsystem_device)
{
LOG_DEBUG("[%s] Nvidia NvAPI Illumination GPU found", device_list[dev_idx].name);
switch(device_list[dev_idx].gpu_rgb_version)
{
case NVIDIA_ILLUMINATION_V1:
{
nvapi_accessor* new_nvapi = new nvapi_accessor(gpu_handles[gpu_idx]);
NVIDIAIlluminationV1Controller* controller = new NVIDIAIlluminationV1Controller(new_nvapi, device_list[dev_idx].treats_rgbw_as_rgb, device_list[dev_idx].name);
RGBController_NVIDIAIlluminationV1* rgb_controller = new RGBController_NVIDIAIlluminationV1(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
break;
}
}
}
}
}
}
REGISTER_DETECTOR("Nvidia NvAPI Illumination", DetectNVIDIAIllumGPUs);
@@ -0,0 +1,190 @@
/*---------------------------------------------------------*\
| NVIDIAIlluminationV1Controller_Windows_Linux.cpp |
| |
| Driver for NVIDIA Illumination V1 GPU |
| |
| Carter Miller (GingerRunner) 05 Jan 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "NVIDIAIlluminationV1Controller_Windows_Linux.h"
NVIDIAIlluminationV1Controller::NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb, std::string dev_name)
{
nvapi = nvapi_ptr;
_treats_rgbw_as_rgb = treats_rgbw_as_rgb;
name = dev_name;
}
NVIDIAIlluminationV1Controller::~NVIDIAIlluminationV1Controller()
{
}
std::string NVIDIAIlluminationV1Controller::GetName()
{
return(name);
}
void NVIDIAIlluminationV1Controller::checkNVAPIreturn()
{
if (nvapi_return != NVAPI_OK)
{
LOG_DEBUG("NVAPI return code not NVAPI_OK: %d", nvapi_return);
}
}
void NVIDIAIlluminationV1Controller::getControl()
{
/*------------------------------------------------------------------------------------------------*\
| This was previously memset(&zone_params, 0, sizeof(zone_params)) |
| But this kind of zero initialization is more up-to-date and safer in the event of non-primitive |
| data types |
\*------------------------------------------------------------------------------------------------*/
zone_params = {};
/*---------------------------------------------------------------------------------------------------*\
| Hardcoded value found via sniffing, this may be different for other cards, once that is |
| found, may be best to simply if/else this based on the card detected or map it out in the detector |
| and then pass via constructor to here. |
\*---------------------------------------------------------------------------------------------------*/
zone_params.version = 72012;
zone_params.bDefault = 0;
/*---------------------------------------------------------------------------------------------------*\
| As far as I can tell, this pre-populates the zone type value, as well as the number of zones |
| able to be controlled, and their existing settings, very useful for extending this controller. |
\*---------------------------------------------------------------------------------------------------*/
nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_GET_CONTROL, &zone_params);
checkNVAPIreturn();
}
void NVIDIAIlluminationV1Controller::setControl()
{
nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_SET_CONTROL, &zone_params);
checkNVAPIreturn();
}
/*----------------------------------------------------------------------------------------------------*\
| This function exists to check if RGB colors are all set to zero, and if so, to take the brightness |
| down to zero. This was done to comply with functionality in OpenRGB such as "Lights Off" which |
| sends RGB values of all zeroes, but doesn't seem to send a brightness of zero at this time (6/2022). |
\*----------------------------------------------------------------------------------------------------*/
bool NVIDIAIlluminationV1Controller::allZero(std::array<uint8_t, 4> colors)
{
return colors == all_zeros;
}
void NVIDIAIlluminationV1Controller::setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness)
{
zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorR = red;
zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorG = green;
zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorB = blue;
zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorW = white;
zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.brightnessPct = brightness;
}
void NVIDIAIlluminationV1Controller::setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness)
{
zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorR = red;
zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorG = green;
zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorB = blue;
zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.brightnessPct = brightness;
}
void NVIDIAIlluminationV1Controller::setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config)
{
getControl();
uint8_t red = RGBGetRValue(zone_config.colors[0]);
uint8_t green = RGBGetGValue(zone_config.colors[0]);
uint8_t blue = RGBGetBValue(zone_config.colors[0]);
uint8_t white = 0;
switch(mode)
{
case NVIDIA_ILLUMINATION_OFF:
zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB;
if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB)
{
setZoneRGB(zone, 0, 0, 0, 0);
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW)
{
setZoneRGBW(zone, 0, 0, 0, 0, 0);
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR)
{
zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = 0;
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED)
{
zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = 0;
}
break;
case NVIDIA_ILLUMINATION_DIRECT:
zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB;
if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB)
{
setZoneRGB(zone, red, green, blue, zone_config.brightness);
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW)
{
/*----------------------------------------------------------------------------------------------------*\
| Certain devices seem to ignore the white value entirely, despite the zone being reported back by the |
| API as RGBW, as such, this if statement was added to conduct a different course of action based |
| on definitions placed in the controller page |
\*----------------------------------------------------------------------------------------------------*/
if(!_treats_rgbw_as_rgb)
{
uint8_t min_rgb_value = 0xFF;
uint8_t max_rgb_value = 0;
min_rgb_value = ((red < 0xFF) ? red : min_rgb_value);
min_rgb_value = ((green < min_rgb_value) ? green : min_rgb_value);
min_rgb_value = ((blue < min_rgb_value) ? blue : min_rgb_value);
max_rgb_value = ((red > 0) ? red : max_rgb_value);
max_rgb_value = ((green > max_rgb_value) ? green : max_rgb_value);
max_rgb_value = ((blue > max_rgb_value) ? blue : max_rgb_value);
/*---------------------------------------------------------------------------------------------------*\
| If difference between the highest and lowest RGB values is 10 or lower, set the white value only, |
| zero out the rest, this logic was found via tedious examination |
\*---------------------------------------------------------------------------------------------------*/
if (max_rgb_value - min_rgb_value <= 10)
{
red = 0;
green = 0;
blue = 0;
white = (max_rgb_value + min_rgb_value)/2;
}
}
setZoneRGBW(zone, red, green, blue, white, zone_config.brightness);
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR)
{
zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness;
}
else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED)
{
zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness;
}
break;
}
setControl();
}
int NVIDIAIlluminationV1Controller::getZoneColor(uint8_t zone_index)
{
return ToRGBColor(zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorR,
zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorG,
zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorB);
}
std::vector<NV_GPU_CLIENT_ILLUM_ZONE_TYPE> NVIDIAIlluminationV1Controller::getInfo()
{
std::vector<NV_GPU_CLIENT_ILLUM_ZONE_TYPE> zone_types;
getControl();
for(unsigned int i = 0; i < zone_params.numIllumZonesControl; i++)
{
zone_types.push_back(zone_params.zones[i].type);
}
return zone_types;
}
@@ -0,0 +1,62 @@
/*---------------------------------------------------------*\
| NVIDIAIlluminationV1Controller_Windows_Linux.h |
| |
| Driver for NVIDIA Illumination V1 GPU |
| |
| Carter Miller (GingerRunner) 04 Jan 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <cstring>
#include <string>
#include <vector>
#include "nvapi_accessor_Windows_Linux.h"
#include "RGBController.h"
#include "LogManager.h"
#define NVIDIA_ILLUMINATION_V1_CONTROLLER_NAME "NVIDIA_ILLUMINATION_V1"
#define NVAPI_OK 0
struct NVIDIAIllumination_Config
{
uint8_t brightness;
RGBColor colors[7];
};
enum
{
NVIDIA_ILLUMINATION_OFF = 0,
NVIDIA_ILLUMINATION_DIRECT = 1
};
class NVIDIAIlluminationV1Controller
{
public:
NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb, std::string dev_name);
~NVIDIAIlluminationV1Controller();
std::string GetName();
void getControl();
void setControl();
bool allZero(std::array<uint8_t, 4> colors);
void setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness);
void setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness);
void setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config);
int getZoneColor(uint8_t zone_index);
std::vector<NV_GPU_CLIENT_ILLUM_ZONE_TYPE> getInfo();
private:
nvapi_accessor* nvapi;
bool _treats_rgbw_as_rgb;
NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS zone_params;
NV_STATUS nvapi_return = 0;
const std::array<uint8_t, 4> all_zeros = {0, 0, 0, 0};
std::string name;
void checkNVAPIreturn();
};
@@ -0,0 +1,168 @@
/*---------------------------------------------------------*\
| RGBController_NVIDIAIllumination_Windows_Linux.cpp |
| |
| RGBController for NVIDIA Illumination GPU |
| |
| Carter Miller (GingerRunner) 04 Jan 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <array>
#include "RGBController_NVIDIAIllumination_Windows_Linux.h"
/**------------------------------------------------------------------*\
@name NVIDIA Illumination
@category GPU
@type PCI
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectNVIDIAIllumGPUs
@comment Tested on various 30 series GPUs and a Founders Edition 2070 Super
If you want to see if your card should also use this controller, download the DLLs from the release of [this](https://gitlab.com/OpenRGBDevelopers/NvAPISpy).
Perform the global replacement technique, which is specified in the README of NvAPI spy. Once this is complete, use an RGB program of your choice and make some basic
lighting changes.
Check the C:\NvAPISpy\ folder and see if the logs created are filled with calls like this:
```
NvAPI_GPU_ClientIllumZonesGetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0
ZoneIdx: 0 ----------------------------------------
**ZoneType: RGBW ControlMode: MANUAL
**DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36
ZoneIdx: 1 ----------------------------------------
**ZoneType: SINGLE_COLOR ControlMode: MANUAL
**DATA_SINGLE_COLOR:: Brightness% 100
NvAPI_GPU_ClientIllumZonesSetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0
ZoneIdx: 0 ----------------------------------------
**ZoneType: RGBW ControlMode: MANUAL
**DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36
ZoneIdx: 1 ----------------------------------------
**ZoneType: SINGLE_COLOR ControlMode: MANUAL
**DATA_SINGLE_COLOR:: Brightness% 44
```
If you see Get/Set Calls above for zone control, please create a [new device issue](https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/new?issuable_template=New%20Device#)
and attach the relevant details to request support for your device (try various modes in each color, especially white and shades around it, since some cards treat RGBW as
standard RGB).
\*-------------------------------------------------------------------*/
RGBController_NVIDIAIlluminationV1::RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* controller_ptr)
{
controller = controller_ptr;
name = controller->GetName();
vendor = "NVIDIA";
description = "NVIDIA Illumination RGB GPU Device";
type = DEVICE_TYPE_GPU;
mode Off;
Off.name = "Off";
Off.value = NVIDIA_ILLUMINATION_OFF;
Off.color_mode = MODE_COLORS_NONE;
modes.push_back(Off);
mode Static;
Static.name = "Direct";
Static.value = NVIDIA_ILLUMINATION_DIRECT;
Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR;
Static.color_mode = MODE_COLORS_PER_LED;
Static.colors_min = 1;
Static.colors_max = 1;
Static.brightness_min = 0;
Static.brightness = 100;
Static.brightness_max = 100;
modes.push_back(Static);
SetupZones();
for(unsigned int i = 0; i < zones.size(); i++)
{
zones[i].colors[0] = controller->getZoneColor(i);
}
}
RGBController_NVIDIAIlluminationV1::~RGBController_NVIDIAIlluminationV1()
{
delete controller;
}
void RGBController_NVIDIAIlluminationV1::UpdateSingleLED(int)
{
DeviceUpdateLEDs();
}
void RGBController_NVIDIAIlluminationV1::SetupZones()
{
/*--------------------------------------------------------------------------*\
| Use the NvAPI to gather existing zones on the card and their capabilities, |
| populate available zones accordingly. |
\*--------------------------------------------------------------------------*/
zoneTypes = controller->getInfo();
nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB] = "RGB";
nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW] = "RGBW";
nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED] = "FIXED COLOR";
nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR] = "SINGLE COLOR";
for(uint8_t zone_idx = 0; zone_idx < zoneTypes.size(); zone_idx++)
{
zone* new_zone = new zone();
led* new_led = new led();
new_zone->name = std::to_string(zone_idx) + " - " + (std::string)nvidia_illum_zone_names[zoneTypes[zone_idx]];
new_zone->type = ZONE_TYPE_SINGLE;
new_zone->leds_min = 1;
new_zone->leds_max = 1;
new_zone->leds_count = 1;
new_zone->matrix_map = NULL;
new_led->name = "Entire Zone";
leds.push_back(*new_led);
zones.push_back(*new_zone);
zoneIndexMap.push_back(zone_idx);
}
SetupColors();
}
void RGBController_NVIDIAIlluminationV1::ResizeZone(int /*zone*/, int /*new_size*/)
{
/*---------------------------------------------------------*\
| This device does not support resizing zones |
\*---------------------------------------------------------*/
}
void RGBController_NVIDIAIlluminationV1::DeviceUpdateLEDs()
{
NVIDIAIllumination_Config nv_zone_config;
for(uint8_t zone_idx = 0; zone_idx < zoneIndexMap.size(); zone_idx++)
{
nv_zone_config.colors[0] = colors[zone_idx];
nv_zone_config.brightness = modes[active_mode].brightness;
controller->setZone(zone_idx, modes[active_mode].value, nv_zone_config);
}
}
void RGBController_NVIDIAIlluminationV1::UpdateZoneLEDs(int zone)
{
NVIDIAIllumination_Config nv_zone_config;
nv_zone_config.colors[0] = colors[zone];
nv_zone_config.brightness = modes[active_mode].brightness;
controller->setZone(zone, modes[active_mode].value, nv_zone_config);
}
uint8_t RGBController_NVIDIAIlluminationV1::getModeIndex(uint8_t mode_value)
{
for(uint8_t mode_index = 0; mode_index < modes.size(); mode_index++)
{
if(modes[mode_index].value == mode_value)
{
return mode_index;
}
}
return 0;
}
void RGBController_NVIDIAIlluminationV1::DeviceUpdateMode()
{
DeviceUpdateLEDs();
}
@@ -0,0 +1,41 @@
/*---------------------------------------------------------*\
| RGBController_NVIDIAIllumination_Windows_Linux.h |
| |
| RGBController for NVIDIA Illumination GPU |
| |
| Carter Miller (GingerRunner) 04 Jan 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#pragma once
#include <map>
#include "RGBController.h"
#include "NVIDIAIlluminationV1Controller_Windows_Linux.h"
#define NVIDIA_FOUNDERS_V1_CONTROLLER_NAME "NVIDIA_FOUNDERS_V1"
class RGBController_NVIDIAIlluminationV1 : public RGBController
{
public:
RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* nvidia_founders_ptr);
~RGBController_NVIDIAIlluminationV1();
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
uint8_t getModeIndex(uint8_t mode_value);
NVIDIAIlluminationV1Controller* controller;
std::vector<uint8_t> zoneIndexMap;
std::vector<NV_GPU_CLIENT_ILLUM_ZONE_TYPE> zoneTypes;
std::map<NV_GPU_CLIENT_ILLUM_ZONE_TYPE, const char *> nvidia_illum_zone_names;
};
@@ -0,0 +1,40 @@
/*---------------------------------------------------------*\
| nvapi_accessor_Windows_Linux.cpp |
| |
| NVAPI accessor for NVIDIA NVAPI illumination API |
| |
| Carter Miller (GingerRunner) 20 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include <chrono>
#include <thread>
#include "nvapi_accessor_Windows_Linux.h"
nvapi_accessor::nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle)
{
this->handle = handle;
}
NV_STATUS nvapi_accessor::nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct)
{
NV_STATUS ret = -1;
if(nvapi_call == NVAPI_ZONE_SET_CONTROL)
{
ret = NvAPI_GPU_ClientIllumZonesSetControl(handle, zone_control_struct);
}
else if(nvapi_call == NVAPI_ZONE_GET_CONTROL)
{
ret = NvAPI_GPU_ClientIllumZonesGetControl(handle, zone_control_struct);
}
/*----------------------------------------------------------------------------------*\
| Based off experimentation, the NvAPI doesn't like to be spammed calls |
| or else it just ignores them, this applies to both get/set control (GingerRunner) |
\*----------------------------------------------------------------------------------*/
std::this_thread::sleep_for(std::chrono::milliseconds(NVAPI_CONTROL_BUFFER_TIME_MS));
return(ret);
}
@@ -0,0 +1,27 @@
/*---------------------------------------------------------*\
| nvapi_accessor_Windows_Linux.h |
| |
| NVAPI accessor for NVIDIA NVAPI illumination API |
| |
| Carter Miller (GingerRunner) 20 Jun 2022 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-or-later |
\*---------------------------------------------------------*/
#include "nvapi.h"
// NVAPI Direct Calls
#define NVAPI_ZONE_GET_CONTROL 0
#define NVAPI_ZONE_SET_CONTROL 1
#define NVAPI_CONTROL_BUFFER_TIME_MS 30
class nvapi_accessor
{
public:
nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle);
NV_STATUS nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct);
private:
NV_PHYSICAL_GPU_HANDLE handle;
};