From 61485cb1334865ffe18e332131aafadacc858de9 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Tue, 19 Dec 2023 17:06:18 +0900 Subject: [PATCH 01/81] refactor(WMTheme): clean up detectOpenbox Simplify the code and implement stricter checking of xml contents. --- src/detection/wmtheme/wmtheme_linux.c | 60 +++++++++++++-------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 70b6d5d9cb..1142fc1e6f 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -1,4 +1,5 @@ #include "wmtheme.h" +#include "common/io/io.h" #include "common/properties.h" #include "common/parsing.h" #include "common/settings.h" @@ -142,50 +143,45 @@ static bool detectOpenbox(const FFstrbuf* dePrettyName, FFstrbuf* themeOrError) else ffStrbufAppendS(&absolutePath, ".config/openbox/rc.xml"); - char* line = NULL; - size_t len = 0; - - FILE* file = fopen(absolutePath.chars, "r"); - if(file == NULL) + FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate(); + if (!ffReadFileBuffer(absolutePath.chars, &content)) { - ffStrbufAppendF(themeOrError, "Couldn't open \"%s\"", absolutePath.chars); - + ffStrbufAppendF(themeOrError, "Couldn't read \"%s\"", absolutePath.chars); return false; } - while(getline(&line, &len, file) != -1) - { - if(strstr(line, "") != 0) - break; - } + const char *themeStart = strstr(content.chars, ""); + if (themeStart == NULL) + goto theme_not_found; - while(getline(&line, &len, file) != -1) - { - if(strstr(line, "") != 0) - { - ffStrbufAppendS(themeOrError, line); - ffStrbufRemoveStrings(themeOrError, 2, (const char*[]) { "", "" }); - ffStrbufTrimRight(themeOrError, '\n'); - ffStrbufTrim(themeOrError, ' '); - break; - } + const char *themeEnd = strstr(themeStart, ""); + if (__builtin_expect(themeEnd == NULL, false)) // very rare case + goto theme_not_found; - if(strstr(line, "") != 0) // sanity check - break; - } + const char *nameStart = strstr(themeStart, ""); + if (nameStart == NULL) + goto name_not_found; - if(line != NULL) - free(line); + const char *nameEnd = strstr(nameStart, ""); + if (nameEnd == NULL || nameEnd > themeEnd) // (nameEnd > themeEnd) means name is not a theme's child + goto name_not_found; - fclose(file); + nameStart += strlen(""); + ffStrbufAppendNS(themeOrError, (uint32_t)(nameEnd - nameStart), nameStart); + ffStrbufTrim(themeOrError, ' '); if(themeOrError->length == 0) - { - ffStrbufAppendF(themeOrError, "Couldn't find theme name in \"%s\"", absolutePath.chars); - return false; - } + goto name_not_found; return true; + +theme_not_found: + ffStrbufAppendF(themeOrError, "Couldn't find theme node in \"%s\"", absolutePath.chars); + return false; + +name_not_found: + ffStrbufAppendF(themeOrError, "Couldn't find theme name in \"%s\"", absolutePath.chars); + return false; } bool ffDetectWmTheme(FFstrbuf* themeOrError) From b8b15c517001fb5faf176b8251ec2b864c174c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Dec 2023 14:51:43 +0800 Subject: [PATCH 02/81] Wifi (macOS): support most auth types --- src/detection/wifi/wifi_apple.m | 34 ++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 07d51599fd..4402b0170a 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -157,7 +157,7 @@ NSDictionary* authType = [apple valueForKey:@"AUTH_TYPE"]; if (authType) { - if ([[authType valueForKey:@"AUTH_LOWER"] intValue] != 1) break; // APPLE80211_AUTH_TYPE_UNICAST? + // AUTH_LOWER seems useless. `airport` verifies if its value is between 1 and 3, and prints `unknown` if not NSNumber* authUpper = [authType valueForKey:@"AUTH_UPPER"]; if (!authUpper) @@ -167,15 +167,39 @@ int authUpperValue = [authUpper intValue]; switch (authUpperValue) { - case 4096: - ffStrbufSetStatic(&item->conn.security, "WPA3-SAE"); + case 1: + ffStrbufSetStatic(&item->conn.security, "WPA"); break; - case 8: - ffStrbufSetStatic(&item->conn.security, "WPA2-PSK"); + case 2: + ffStrbufSetStatic(&item->conn.security, "WPA-PSK"); break; case 4: ffStrbufSetStatic(&item->conn.security, "WPA2"); break; + case 8: + ffStrbufSetStatic(&item->conn.security, "WPA2-PSK"); + break; + case 16: + ffStrbufSetStatic(&item->conn.security, "FT-WPA2-PSK"); + break; + case 32: + ffStrbufSetStatic(&item->conn.security, "LEAP"); + break; + case 64: + ffStrbufSetStatic(&item->conn.security, "802.1X"); + break; + case 128: + ffStrbufSetStatic(&item->conn.security, "FT-WPA2"); + break; + case 256: + ffStrbufSetStatic(&item->conn.security, "WPS"); + break; + case 4096: + ffStrbufSetStatic(&item->conn.security, "WPA3-SAE"); + break; + case 8192: + ffStrbufSetStatic(&item->conn.security, "WPA3-FT-SAE"); + break; default: // TODO: support more auth types ffStrbufAppendF(&item->conn.security, "To be supported (%d)", authUpperValue); break; From 456a58c8f57aaf22c51571ec0ead1e7c40c3d860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Dec 2023 15:26:51 +0800 Subject: [PATCH 03/81] fastfetch: default preset names to `.jsonc` Fix #666 --- src/fastfetch.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/fastfetch.c b/src/fastfetch.c index 0d758dbbdc..f37d14bd53 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -501,6 +501,11 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val ffStrbufAppendS(&absolutePath, value); bool success = isJsonConfig ? parseJsoncFile(absolutePath.chars) : parseConfigFile(data, absolutePath.chars); + if (!success) + { + ffStrbufAppendS(&absolutePath, ".jsonc"); + success = parseJsoncFile(absolutePath.chars); + } if(success) return; @@ -514,6 +519,11 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val ffStrbufAppendS(&absolutePath, value); bool success = isJsonConfig ? parseJsoncFile(absolutePath.chars) : parseConfigFile(data, absolutePath.chars); + if (!success) + { + ffStrbufAppendS(&absolutePath, ".jsonc"); + success = parseJsoncFile(absolutePath.chars); + } if(success) return; From 2f4b210f33e17086fcda6da3fc3fc9ff071b2aef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 19 Dec 2023 09:22:00 +0800 Subject: [PATCH 04/81] CI: generate sha256sum --- .github/workflows/ci.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5639360129..938bc5058e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,7 +132,7 @@ jobs: run: echo "ffversion=$(./fastfetch --version-raw)" >> $GITHUB_OUTPUT - name: upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fastfetch-linux path: ./fastfetch-*.* @@ -188,7 +188,7 @@ jobs: run: ctest - name: upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fastfetch-macos path: ./fastfetch-*.* @@ -204,7 +204,7 @@ jobs: uses: actions/checkout@v4 - name: run VM - uses: cross-platform-actions/action@v0.21.1 + uses: cross-platform-actions/action@master with: operating_system: freebsd version: '13.2' @@ -222,7 +222,7 @@ jobs: ctest - name: upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fastfetch-freebsd path: ./fastfetch-*.* @@ -284,7 +284,7 @@ jobs: run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win64.7z *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fastfetch-win64 path: ./fastfetch-*-Win64.* @@ -351,7 +351,7 @@ jobs: run: 7z a -t7z -mx9 -bd -y fastfetch-$(./fastfetch --version-raw)-Win32.7z *.dll fastfetch.exe flashfetch.exe presets - name: upload artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: fastfetch-win32 path: ./fastfetch-*-Win32.* @@ -370,7 +370,7 @@ jobs: contents: write steps: - name: download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 - name: get latest release version id: get_version_release @@ -378,11 +378,20 @@ jobs: with: repository: ${{ github.repository }} + - name: generate release-notes + run: | + ls fastfetch-*/* + echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md#${{ needs.linux.outputs.ffversion }}) for details." > fastfetch-release-notes.md + echo -e "\n---\n\n
SHA256SUMs
\n\n\`\`\`" >> fastfetch-release-notes.md + sha256sum fastfetch-*/* >> fastfetch-release-notes.md + echo -e "\n\`\`\`\n
" >> fastfetch-release-notes.md + - name: create release if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release uses: ncipollo/release-action@v1 with: tag: ${{ needs.linux.outputs.ffversion }} commit: ${{ github.sha }} + bodyFile: fastfetch-release-notes.md artifactErrorsFailBuild: true - artifacts: fastfetch-linux/*,fastfetch-macos/*,fastfetch-freebsd/*,fastfetch-win64/*,fastfetch-win32/* + artifacts: fastfetch-*/* From 961e9a6a5f4fb61b454632b13d02db19a6cefd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 00:49:56 +0800 Subject: [PATCH 05/81] GPU (Windows): detection with intel driver (WIP) --- CMakeLists.txt | 1 + src/3rdparty/igcl/README.md | 15 + src/3rdparty/igcl/igcl_api.h | 7649 +++++++++++++++++++++++++++++++ src/3rdparty/igcl/repo.json | 6 + src/detection/gpu/gpu_intel.c | 152 + src/detection/gpu/gpu_intel.h | 23 + src/detection/gpu/gpu_windows.c | 28 + 7 files changed, 7874 insertions(+) create mode 100644 src/3rdparty/igcl/README.md create mode 100644 src/3rdparty/igcl/igcl_api.h create mode 100644 src/3rdparty/igcl/repo.json create mode 100644 src/detection/gpu/gpu_intel.c create mode 100644 src/detection/gpu/gpu_intel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b9072d5d61..f0c8c3779c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -630,6 +630,7 @@ elseif(WIN32) src/detection/font/font_windows.c src/detection/gpu/gpu_windows.c src/detection/gpu/gpu_nvidia.c + src/detection/gpu/gpu_intel.c src/detection/host/host_windows.c src/detection/icons/icons_windows.c src/detection/libc/libc_windows.cpp diff --git a/src/3rdparty/igcl/README.md b/src/3rdparty/igcl/README.md new file mode 100644 index 0000000000..12f3e4b90a --- /dev/null +++ b/src/3rdparty/igcl/README.md @@ -0,0 +1,15 @@ +# Intel Graphics Control Library (IGCL) +Header, wrapper library and samples of IGCL version 1.0 + + +# Introduction +IGCL is meant to be a collection of high level APIs for all control aspects of hardware, primarily graphics. This is replacement of legacy Intel CUISDK which used to be released only to OEM's and selected customers. IGCL allows global control and tweaking of display, media & 3D capabilities. + +# Notes +* IGCL binaries are distributed as part of Intel Graphics driver package. +* Header & library wrapper code are provided here to help developers with their application development. +* For API/spec questions or issues, for now, use the "Issues" tab under Github. For issues related to an already shipped binary of this spec, contact standard Intel customer support for Graphics. +* Performance & Telemetry API's, i.e., Engine/Fan/Telemetry/Frequency/Memory/Overclock/PCI/Power/Temperature are limited to 64-bit applications as of now. This is a Level0 limitation. + +# Usage +cmake.exe -B -S -G "Visual Studio 17 2022" -A x64 diff --git a/src/3rdparty/igcl/igcl_api.h b/src/3rdparty/igcl/igcl_api.h new file mode 100644 index 0000000000..ff83226c57 --- /dev/null +++ b/src/3rdparty/igcl/igcl_api.h @@ -0,0 +1,7649 @@ +//=========================================================================== +// Copyright (C) 2022-23 Intel Corporation +// This software and the related documents are Intel copyrighted materials, and +// your use of them is governed by the express license under which they were +// provided to you ("License"). Unless the License provides otherwise, you may +// not use, modify, copy, publish, distribute, disclose or transmit this software +// or the related documents without Intel's prior written permission. This software +// and the related documents are provided as is, with no express or implied +// warranties, other than those that are expressly stated in the License. +//-------------------------------------------------------------------------- + +/** + * + * @file ctl_api.h + * @version v1-r1 + * + */ +#ifndef _CTL_API_H +#define _CTL_API_H +#if defined(__cplusplus) +#pragma once +#endif + +// standard headers +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +// Intel 'ctlApi' common types +#if !defined(__GNUC__) +#pragma region common +#endif +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAKE_VERSION +/// @brief Generates generic ::'ctlApi' API versions +#define CTL_MAKE_VERSION( _major, _minor ) (( _major << 16 )|( _minor & 0x0000ffff)) +#endif // CTL_MAKE_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAJOR_VERSION +/// @brief Extracts ::'ctlApi' API major version +#define CTL_MAJOR_VERSION( _ver ) ( _ver >> 16 ) +#endif // CTL_MAJOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MINOR_VERSION +/// @brief Extracts ::'ctlApi' API minor version +#define CTL_MINOR_VERSION( _ver ) ( _ver & 0x0000ffff ) +#endif // CTL_MINOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_MAJOR_VERSION +/// @brief ::'ctlApi' API major version of this implementation +#define CTL_IMPL_MAJOR_VERSION 1 +#endif // CTL_IMPL_MAJOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_MINOR_VERSION +/// @brief ::'ctlApi' API minor version of this implementation +#define CTL_IMPL_MINOR_VERSION 1 +#endif // CTL_IMPL_MINOR_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_IMPL_VERSION +/// @brief ::'ctlApi' API version of this implementation +#define CTL_IMPL_VERSION CTL_MAKE_VERSION( CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION ) +#endif // CTL_IMPL_VERSION + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_APICALL +#if defined(_WIN32) +/// @brief Calling convention for all API functions +#define CTL_APICALL __cdecl +#else +#define CTL_APICALL +#endif // defined(_WIN32) +#endif // CTL_APICALL + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_APIEXPORT +#if defined(_WIN32) +/// @brief Microsoft-specific dllexport storage-class attribute +#define CTL_APIEXPORT __declspec(dllexport) +#else +#define CTL_APIEXPORT +#endif // defined(_WIN32) +#endif // CTL_APIEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_DLLEXPORT +#if defined(_WIN32) +/// @brief Microsoft-specific dllexport storage-class attribute +#define CTL_DLLEXPORT __declspec(dllexport) +#endif // defined(_WIN32) +#endif // CTL_DLLEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_DLLEXPORT +#if __GNUC__ >= 4 +/// @brief GCC-specific dllexport storage-class attribute +#define CTL_DLLEXPORT __attribute__ ((visibility ("default"))) +#else +#define CTL_DLLEXPORT +#endif // __GNUC__ >= 4 +#endif // CTL_DLLEXPORT + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_BIT +/// @brief Generic macro for enumerator bit masks +#define CTL_BIT( _i ) ( 1 << _i ) +#endif // CTL_BIT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported initialization flags +typedef uint32_t ctl_init_flags_t; +typedef enum _ctl_init_flag_t +{ + CTL_INIT_FLAG_USE_LEVEL_ZERO = CTL_BIT(0), ///< Use Level0 or not. This is usually required for telemetry, + ///< performance, frequency related APIs + CTL_INIT_FLAG_MAX = 0x80000000 + +} ctl_init_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Version information +typedef uint32_t ctl_version_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a control API instance +typedef struct _ctl_api_handle_t *ctl_api_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device adapter instance +typedef struct _ctl_device_adapter_handle_t *ctl_device_adapter_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device temperature sensor +typedef struct _ctl_temp_handle_t *ctl_temp_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle for a device frequency domain +typedef struct _ctl_freq_handle_t *ctl_freq_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a power device. +typedef struct _ctl_pwr_handle_t *ctl_pwr_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device fan +typedef struct _ctl_fan_handle_t *ctl_fan_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device memory module +typedef struct _ctl_mem_handle_t *ctl_mem_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a device engine group +typedef struct _ctl_engine_handle_t *ctl_engine_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Base for all properties types +typedef struct _ctl_base_interface_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + +} ctl_base_interface_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Value type +typedef enum _ctl_property_value_type_t +{ + CTL_PROPERTY_VALUE_TYPE_BOOL = 0, ///< Boolean + CTL_PROPERTY_VALUE_TYPE_FLOAT = 1, ///< Float + CTL_PROPERTY_VALUE_TYPE_INT32 = 2, ///< Int32 + CTL_PROPERTY_VALUE_TYPE_UINT32 = 3, ///< Unsigned Int32 + CTL_PROPERTY_VALUE_TYPE_ENUM = 4, ///< Enum + CTL_PROPERTY_VALUE_TYPE_CUSTOM = 5, ///< Custom argument + CTL_PROPERTY_VALUE_TYPE_MAX + +} ctl_property_value_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details, a generic struct to hold min/max/step size +/// information of various feature properties +typedef struct _ctl_property_range_info_t +{ + float min_possible_value; ///< [out] Minimum possible value + float max_possible_value; ///< [out] Maximum possible value + float step_size; ///< [out] Step size possible + float default_value; ///< [out] Default value + +} ctl_property_range_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details of integer type, a generic struct to hold +/// min/max/step size information of various feature properties +typedef struct _ctl_property_range_info_int_t +{ + int32_t min_possible_value; ///< [out] Minimum possible value + int32_t max_possible_value; ///< [out] Maximum possible value + int32_t step_size; ///< [out] Step size possible + int32_t default_value; ///< [out] Default value + +} ctl_property_range_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property range details of unsigned integer type, a generic struct to +/// hold min/max/step size information of various feature properties +typedef struct _ctl_property_range_info_uint_t +{ + uint32_t min_possible_value; ///< [out] Minimum possible value + uint32_t max_possible_value; ///< [out] Maximum possible value + uint32_t step_size; ///< [out] Step size possible + uint32_t default_value; ///< [out] Default value + +} ctl_property_range_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Bool feature details +typedef struct _ctl_property_info_boolean_t +{ + bool DefaultState; ///< [out] Default state + +} ctl_property_info_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Bool feature for get/set +typedef struct _ctl_property_boolean_t +{ + bool Enable; ///< [in,out] Enable + +} ctl_property_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumeration feature details +typedef struct _ctl_property_info_enum_t +{ + uint64_t SupportedTypes; ///< [out] Supported possible values represented as a bitmask + uint32_t DefaultType; ///< [out] Default type + +} ctl_property_info_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumeration feature for get/set +typedef struct _ctl_property_enum_t +{ + uint32_t EnableType; ///< [in,out] Enable with specific type + +} ctl_property_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Float feature details +typedef struct _ctl_property_info_float_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Float feature for get/set +typedef struct _ctl_property_float_t +{ + bool Enable; ///< [in,out] Enable + float Value; ///< [in,out] Value + +} ctl_property_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature details +typedef struct _ctl_property_info_int_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_int_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature for get/set +typedef struct _ctl_property_int_t +{ + bool Enable; ///< [in,out] Enable + int32_t Value; ///< [in,out] Value + +} ctl_property_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature details +typedef struct _ctl_property_info_uint_t +{ + bool DefaultEnable; ///< [in,out] DefaultEnable + ctl_property_range_info_uint_t RangeInfo; ///< [out] Min/max/default/step details + +} ctl_property_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Int32 feature for get/set +typedef struct _ctl_property_uint_t +{ + bool Enable; ///< [in,out] Enable + uint32_t Value; ///< [in,out] Value + +} ctl_property_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature element details, union of bool/float/enum property_info +/// structs. Used for feature specific capability check +typedef union _ctl_property_info_t +{ + ctl_property_info_boolean_t BoolType; ///< [in,out] Boolean type fields + ctl_property_info_float_t FloatType; ///< [in,out] Float type fields + ctl_property_info_int_t IntType; ///< [in,out] Int type fields + ctl_property_info_enum_t EnumType; ///< [in,out] Enum type fields + ctl_property_info_uint_t UIntType; ///< [in,out] Unsigned Int type fields + +} ctl_property_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature element details, union of bool/float/enum property structs. +/// Used for get/set calls +typedef union _ctl_property_t +{ + ctl_property_boolean_t BoolType; ///< [in,out] Boolean type fields + ctl_property_float_t FloatType; ///< [in,out] Float type fields + ctl_property_int_t IntType; ///< [in,out] Int type fields + ctl_property_enum_t EnumType; ///< [in,out] Enum type fields + ctl_property_uint_t UIntType; ///< [in,out] Unsigned Int type fields + +} ctl_property_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Defines Return/Error codes. +/// All generic error (bit30) codes are between 0x40000000-0x4000FFFF. +/// All 3D (bit 29) specific error codes are between 0x60000000-0x6000FFFF. +/// All media (bit 28) specific error codes are between 0x50000000-0x5000FFFF. +/// All display (bit 27) specific error codes are between 0x48000000-0x4800FFFF +/// All core (bit 26) specific error codes are between 0x44000000-0x4400FFFF +/// Success result code with additional info are between 0x00000001-0x0000FFFF. +typedef enum _ctl_result_t +{ + CTL_RESULT_SUCCESS = 0x00000000, ///< success + CTL_RESULT_SUCCESS_STILL_OPEN_BY_ANOTHER_CALLER = 0x00000001, ///< success but still open by another caller + CTL_RESULT_ERROR_SUCCESS_END = 0x0000FFFF, ///< "Success group error code end value, not to be used + ///< " + CTL_RESULT_ERROR_GENERIC_START = 0x40000000, ///< Generic error code starting value, not to be used + CTL_RESULT_ERROR_NOT_INITIALIZED = 0x40000001, ///< Result not initialized + CTL_RESULT_ERROR_ALREADY_INITIALIZED = 0x40000002, ///< Already initialized + CTL_RESULT_ERROR_DEVICE_LOST = 0x40000003, ///< Device hung, reset, was removed, or driver update occurred + CTL_RESULT_ERROR_OUT_OF_HOST_MEMORY = 0x40000004, ///< Insufficient host memory to satisfy call + CTL_RESULT_ERROR_OUT_OF_DEVICE_MEMORY = 0x40000005, ///< Insufficient device memory to satisfy call + CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS = 0x40000006, ///< Access denied due to permission level + CTL_RESULT_ERROR_NOT_AVAILABLE = 0x40000007, ///< Resource was removed + CTL_RESULT_ERROR_UNINITIALIZED = 0x40000008, ///< Library not initialized + CTL_RESULT_ERROR_UNSUPPORTED_VERSION = 0x40000009, ///< Generic error code for unsupported versions + CTL_RESULT_ERROR_UNSUPPORTED_FEATURE = 0x4000000a, ///< Generic error code for unsupported features + CTL_RESULT_ERROR_INVALID_ARGUMENT = 0x4000000b, ///< Generic error code for invalid arguments + CTL_RESULT_ERROR_INVALID_API_HANDLE = 0x4000000c, ///< API handle in invalid + CTL_RESULT_ERROR_INVALID_NULL_HANDLE = 0x4000000d, ///< Handle argument is not valid + CTL_RESULT_ERROR_INVALID_NULL_POINTER = 0x4000000e, ///< Pointer argument may not be nullptr + CTL_RESULT_ERROR_INVALID_SIZE = 0x4000000f, ///< Size argument is invalid (e.g., must not be zero) + CTL_RESULT_ERROR_UNSUPPORTED_SIZE = 0x40000010, ///< Size argument is not supported by the device (e.g., too large) + CTL_RESULT_ERROR_UNSUPPORTED_IMAGE_FORMAT = 0x40000011, ///< Image format is not supported by the device + CTL_RESULT_ERROR_DATA_READ = 0x40000012, ///< Data read error + CTL_RESULT_ERROR_DATA_WRITE = 0x40000013, ///< Data write error + CTL_RESULT_ERROR_DATA_NOT_FOUND = 0x40000014, ///< Data not found error + CTL_RESULT_ERROR_NOT_IMPLEMENTED = 0x40000015, ///< Function not implemented + CTL_RESULT_ERROR_OS_CALL = 0x40000016, ///< Operating system call failure + CTL_RESULT_ERROR_KMD_CALL = 0x40000017, ///< Kernel mode driver call failure + CTL_RESULT_ERROR_UNLOAD = 0x40000018, ///< Library unload failure + CTL_RESULT_ERROR_ZE_LOADER = 0x40000019, ///< Level0 loader not found + CTL_RESULT_ERROR_INVALID_OPERATION_TYPE = 0x4000001a, ///< Invalid operation type + CTL_RESULT_ERROR_NULL_OS_INTERFACE = 0x4000001b,///< Null OS interface + CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE = 0x4000001c, ///< Null OS adapter handle + CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE = 0x4000001d,///< Null display output handle + CTL_RESULT_ERROR_WAIT_TIMEOUT = 0x4000001e, ///< Timeout in Wait function + CTL_RESULT_ERROR_PERSISTANCE_NOT_SUPPORTED = 0x4000001f,///< Persistance not supported + CTL_RESULT_ERROR_PLATFORM_NOT_SUPPORTED = 0x40000020, ///< Platform not supported + CTL_RESULT_ERROR_UNKNOWN_APPLICATION_UID = 0x40000021, ///< Unknown Appplicaion UID in Initialization call + CTL_RESULT_ERROR_INVALID_ENUMERATION = 0x40000022, ///< The enum is not valid + CTL_RESULT_ERROR_FILE_DELETE = 0x40000023, ///< Error in file delete operation + CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED = 0x40000024,///< The device requires a reset. + CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED = 0x40000025, ///< The device requires a full reboot. + CTL_RESULT_ERROR_LOAD = 0x40000026, ///< Library load failure + CTL_RESULT_ERROR_UNKNOWN = 0x4000FFFF, ///< Unknown or internal error + CTL_RESULT_ERROR_RETRY_OPERATION = 0x40010000, ///< Operation failed, retry previous operation again + CTL_RESULT_ERROR_GENERIC_END = 0x4000FFFF, ///< "Generic error code end value, not to be used + ///< " + CTL_RESULT_ERROR_CORE_START = 0x44000000, ///< Core error code starting value, not to be used + CTL_RESULT_ERROR_CORE_OVERCLOCK_NOT_SUPPORTED = 0x44000001, ///< The Overclock is not supported. + CTL_RESULT_ERROR_CORE_OVERCLOCK_VOLTAGE_OUTSIDE_RANGE = 0x44000002, ///< The Voltage exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_FREQUENCY_OUTSIDE_RANGE = 0x44000003, ///< The Frequency exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_POWER_OUTSIDE_RANGE = 0x44000004, ///< The Power exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_TEMPERATURE_OUTSIDE_RANGE = 0x44000005, ///< The Power exceeds the acceptable min/max. + CTL_RESULT_ERROR_CORE_OVERCLOCK_IN_VOLTAGE_LOCKED_MODE = 0x44000006,///< The Overclock is in voltage locked mode. + CTL_RESULT_ERROR_CORE_OVERCLOCK_RESET_REQUIRED = 0x44000007,///< It indicates that the requested change will not be applied until the + ///< device is reset. + CTL_RESULT_ERROR_CORE_OVERCLOCK_WAIVER_NOT_SET = 0x44000008,///< The $OverclockWaiverSet function has not been called. + CTL_RESULT_ERROR_CORE_END = 0x0440FFFF, ///< "Core error code end value, not to be used + ///< " + CTL_RESULT_ERROR_3D_START = 0x60000000, ///< 3D error code starting value, not to be used + CTL_RESULT_ERROR_3D_END = 0x6000FFFF, ///< "3D error code end value, not to be used + ///< " + CTL_RESULT_ERROR_MEDIA_START = 0x50000000, ///< Media error code starting value, not to be used + CTL_RESULT_ERROR_MEDIA_END = 0x5000FFFF, ///< "Media error code end value, not to be used + ///< " + CTL_RESULT_ERROR_DISPLAY_START = 0x48000000, ///< Display error code starting value, not to be used + CTL_RESULT_ERROR_INVALID_AUX_ACCESS_FLAG = 0x48000001, ///< Invalid flag for Aux access + CTL_RESULT_ERROR_INVALID_SHARPNESS_FILTER_FLAG = 0x48000002,///< Invalid flag for Sharpness + CTL_RESULT_ERROR_DISPLAY_NOT_ATTACHED = 0x48000003, ///< Error for Display not attached + CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE = 0x48000004, ///< Error for display attached but not active + CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG = 0x48000005, ///< Error for invalid power optimization flag + CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST = 0x48000006,///< DPST is supported only in DC Mode + CTL_RESULT_ERROR_INVALID_PIXTX_GET_CONFIG_QUERY_TYPE = 0x48000007, ///< Invalid query type for pixel transformation get configuration + CTL_RESULT_ERROR_INVALID_PIXTX_SET_CONFIG_OPERATION_TYPE = 0x48000008, ///< Invalid operation type for pixel transformation set configuration + CTL_RESULT_ERROR_INVALID_SET_CONFIG_NUMBER_OF_SAMPLES = 0x48000009, ///< Invalid number of samples for pixel transformation set configuration + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID = 0x4800000a, ///< Invalid block id for pixel transformation + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_TYPE = 0x4800000b, ///< Invalid block type for pixel transformation + CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_NUMBER = 0x4800000c, ///< Invalid block number for pixel transformation + CTL_RESULT_ERROR_INSUFFICIENT_PIXTX_BLOCK_CONFIG_MEMORY = 0x4800000d, ///< Insufficient memery allocated for BlockConfigs + CTL_RESULT_ERROR_3DLUT_INVALID_PIPE = 0x4800000e, ///< Invalid pipe for 3dlut + CTL_RESULT_ERROR_3DLUT_INVALID_DATA = 0x4800000f, ///< Invalid 3dlut data + CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR = 0x48000010, ///< 3dlut not supported in HDR + CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION = 0x48000011, ///< Invalid 3dlut operation + CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL = 0x48000012, ///< 3dlut call unsuccessful + CTL_RESULT_ERROR_AUX_DEFER = 0x48000013, ///< AUX defer failure + CTL_RESULT_ERROR_AUX_TIMEOUT = 0x48000014, ///< AUX timeout failure + CTL_RESULT_ERROR_AUX_INCOMPLETE_WRITE = 0x48000015, ///< AUX incomplete write failure + CTL_RESULT_ERROR_I2C_AUX_STATUS_UNKNOWN = 0x48000016, ///< I2C/AUX unkonown failure + CTL_RESULT_ERROR_I2C_AUX_UNSUCCESSFUL = 0x48000017, ///< I2C/AUX unsuccessful + CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED = 0x48000018,///< Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data + ///< passed by user + CTL_RESULT_ERROR_EXTERNAL_DISPLAY_ATTACHED = 0x48000019,///< External Display is Attached hence fail the Display Switch + CTL_RESULT_ERROR_CUSTOM_MODE_STANDARD_CUSTOM_MODE_EXISTS = 0x4800001a, ///< Standard custom mode exists + CTL_RESULT_ERROR_CUSTOM_MODE_NON_CUSTOM_MATCHING_MODE_EXISTS = 0x4800001b, ///< Non custom matching mode exists + CTL_RESULT_ERROR_CUSTOM_MODE_INSUFFICIENT_MEMORY = 0x4800001c, ///< Custom mode insufficent memory + CTL_RESULT_ERROR_ADAPTER_ALREADY_LINKED = 0x4800001d, ///< Adapter is already linked + CTL_RESULT_ERROR_ADAPTER_NOT_IDENTICAL = 0x4800001e,///< Adapter is not identical for linking + CTL_RESULT_ERROR_ADAPTER_NOT_SUPPORTED_ON_LDA_SECONDARY = 0x4800001f, ///< Adapter is LDA Secondary, so not supporting requested operation + CTL_RESULT_ERROR_SET_FBC_FEATURE_NOT_SUPPORTED = 0x48000020,///< Set FBC Feature not supported + CTL_RESULT_ERROR_DISPLAY_END = 0x4800FFFF, ///< "Display error code end value, not to be used + ///< " + CTL_RESULT_MAX + +} ctl_result_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_DEVICE_NAME_LEN +/// @brief Maximum IPC handle size +#define CTL_MAX_DEVICE_NAME_LEN 100 +#endif // CTL_MAX_DEVICE_NAME_LEN + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_RESERVED_SIZE +/// @brief Maximum reserved size for future members. +#define CTL_MAX_RESERVED_SIZE 112 +#endif // CTL_MAX_RESERVED_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief General Physical Units. +typedef enum _ctl_units_t +{ + CTL_UNITS_FREQUENCY_MHZ = 0, ///< Type is Frequency with units in MHz. + CTL_UNITS_OPERATIONS_GTS = 1, ///< Type is Frequency with units in GT/s (gigatransfers per second). + CTL_UNITS_OPERATIONS_MTS = 2, ///< Type is Frequency with units in MT/s (megatransfers per second). + CTL_UNITS_VOLTAGE_VOLTS = 3, ///< Type is Voltage with units in Volts. + CTL_UNITS_POWER_WATTS = 4, ///< Type is Power with units in Watts. + CTL_UNITS_TEMPERATURE_CELSIUS = 5, ///< Type is Temperature with units in Celsius. + CTL_UNITS_ENERGY_JOULES = 6, ///< Type is Energy with units in Joules. + CTL_UNITS_TIME_SECONDS = 7, ///< Type is Time with units in Seconds. + CTL_UNITS_MEMORY_BYTES = 8, ///< Type is Memory with units in Bytes. + CTL_UNITS_ANGULAR_SPEED_RPM = 9, ///< Type is Angular Speed with units in Revolutions per Minute. + CTL_UNITS_POWER_MILLIWATTS = 10, ///< Type is Power with units in MilliWatts. + CTL_UNITS_PERCENT = 11, ///< Type is Percentage. + CTL_UNITS_MEM_SPEED_GBPS = 12, ///< Type is Memory Speed in Gigabyte per Seconds (Gbps) + CTL_UNITS_VOLTAGE_MILLIVOLTS = 13, ///< Type is Voltage with units in milliVolts. + CTL_UNITS_UNKNOWN = 0x4800FFFF, ///< Type of units unknown. + CTL_UNITS_MAX + +} ctl_units_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief General Data Types. +typedef enum _ctl_data_type_t +{ + CTL_DATA_TYPE_INT8 = 0, ///< The data type is 8 bit signed integer. + CTL_DATA_TYPE_UINT8 = 1, ///< The data type is 8 bit unsigned integer. + CTL_DATA_TYPE_INT16 = 2, ///< The data type is 16 bit signed integer. + CTL_DATA_TYPE_UINT16 = 3, ///< The data type is 16 bit unsigned integer. + CTL_DATA_TYPE_INT32 = 4, ///< The data type is 32 bit signed integer. + CTL_DATA_TYPE_UINT32 = 5, ///< The data type is 32 bit unsigned integer. + CTL_DATA_TYPE_INT64 = 6, ///< The data type is 64 bit signed integer. + CTL_DATA_TYPE_UINT64 = 7, ///< The data type is 64 bit unsigned integer. + CTL_DATA_TYPE_FLOAT = 8, ///< The data type is 32 bit floating point. + CTL_DATA_TYPE_DOUBLE = 9, ///< The data type is 64 bit floating point. + CTL_DATA_TYPE_STRING_ASCII = 10, ///< The data type is an array of 8 bit unsigned integers. + CTL_DATA_TYPE_STRING_UTF16 = 11, ///< The data type is an array of 16 bit unsigned integers. + CTL_DATA_TYPE_STRING_UTF132 = 12, ///< The data type is an array of 32 bit unsigned integers. + CTL_DATA_TYPE_UNKNOWN = 0x4800FFFF, ///< The data type is unknown. + CTL_DATA_TYPE_MAX + +} ctl_data_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Union for Generic Data. +/// +/// @details +/// - The telemetry data items could be of different types. +/// - Refer to ::ctl_data_type_t to find the current type. +typedef union _ctl_data_value_t +{ + int8_t data8; ///< [out] The data type is 8 bit signed integer. + uint8_t datau8; ///< [out] The data type is 8 bit unsigned integer. + int16_t data16; ///< [out] The data type is 16 bit signed integer. + uint16_t datau16; ///< [out] The data type is 16 bit unsigned integer. + int32_t data32; ///< [out] The data type is 32 bit signed integer. + uint32_t datau32; ///< [out] The data type is 32 bit unsigned integer. + int64_t data64; ///< [out] The data type is 64 bit signed integer. + uint64_t datau64; ///< [out] The data type is 64 bit unsigned integer. + float datafloat; ///< [out] The data type is 32 bit floating point. + double datadouble; ///< [out] The data type is 64 bit floating point. + +} ctl_data_value_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Base for all properties types +typedef struct _ctl_base_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + +} ctl_base_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Application Unique ID +typedef struct _ctl_application_id_t +{ + uint32_t Data1; ///< [in] Data1 + uint16_t Data2; ///< [in] Data2 + uint16_t Data3; ///< [in] Data3 + uint8_t Data4[8]; ///< [in] Data4 + +} ctl_application_id_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Init arguments +typedef struct _ctl_init_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_version_info_t AppVersion; ///< [in][release] App's IGCL version + ctl_init_flags_t flags; ///< [in][release] Caller version + ctl_version_info_t SupportedVersion; ///< [out][release] IGCL implementation version + ctl_application_id_t ApplicationUID; ///< [in] Application Provided Unique ID.Application can pass all 0's as + ///< the default ID + +} ctl_init_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved struct +typedef struct _ctl_reserved_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + void* pSpecialArg; ///< [in] Reserved struct + uint32_t ArgSize; ///< [in] struct size + +} ctl_reserved_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved base struct +typedef struct _ctl_reserved_args_base_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + +} ctl_reserved_args_base_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved - Unlock function capability +typedef struct _ctl_unlock_capability_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + ctl_application_id_t UnlockCapsID; ///< [in] Unique ID to unlock a specific function + +} ctl_unlock_capability_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Used by loader like modules to specify runtime implementation details +typedef struct _ctl_runtime_path_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_application_id_t UnlockID; ///< [in] Unique ID for reserved/special function + wchar_t* pRuntimePath; ///< [in] Path to runtime DLL + uint16_t DeviceID; ///< [in] Device ID of interest to caller. pRuntimePath should not be NULL. + uint8_t RevID; ///< [in] Revision ID of interest to caller. pRuntimePath should not be + ///< NULL. + +} ctl_runtime_path_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Control Api Init +/// +/// @details +/// - Control Api Init +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pInitDesc` +/// + `nullptr == phAPIHandle` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlInit( + ctl_init_args_t* pInitDesc, ///< [in][out] App's control API version + ctl_api_handle_t* phAPIHandle ///< [in][out][release] Control API handle + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Control Api Destroy +/// +/// @details +/// - Control Api Close +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlClose( + ctl_api_handle_t hAPIHandle ///< [in][release] Control API implementation handle obtained during init + ///< call + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Runtime path +/// +/// @details +/// - Control Api set runtime path. Optional call from a loader which allows +/// the loaded runtime to enumerate only the adapters which the specified +/// runtime is responsible for. This is done usually by a loader or by +/// callers who know how to get the specific runtime of interest. This +/// call right now is reserved for use by Intel components. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetRuntimePath( + ctl_runtime_path_args_t* pArgs ///< [in] Runtime path + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported Functions +typedef uint32_t ctl_supported_functions_flags_t; +typedef enum _ctl_supported_functions_flag_t +{ + CTL_SUPPORTED_FUNCTIONS_FLAG_DISPLAY = CTL_BIT(0), ///< [out] Is Display supported + CTL_SUPPORTED_FUNCTIONS_FLAG_3D = CTL_BIT(1), ///< [out] Is 3D supported + CTL_SUPPORTED_FUNCTIONS_FLAG_MEDIA = CTL_BIT(2),///< [out] Is Media supported + CTL_SUPPORTED_FUNCTIONS_FLAG_MAX = 0x80000000 + +} ctl_supported_functions_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Firmware version +typedef struct _ctl_firmware_version_t +{ + uint64_t major_version; ///< [out] Major version + uint64_t minor_version; ///< [out] Minor version + uint64_t build_number; ///< [out] Build number + +} ctl_firmware_version_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief DeviceType +typedef enum _ctl_device_type_t +{ + CTL_DEVICE_TYPE_GRAPHICS = 1, ///< Graphics Device type + CTL_DEVICE_TYPE_SYSTEM = 2, ///< System Device type + CTL_DEVICE_TYPE_MAX + +} ctl_device_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adapter Properties +typedef uint32_t ctl_adapter_properties_flags_t; +typedef enum _ctl_adapter_properties_flag_t +{ + CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED = CTL_BIT(0),///< [out] Is Integrated Graphics adapter + CTL_ADAPTER_PROPERTIES_FLAG_LDA_PRIMARY = CTL_BIT(1), ///< [out] Is Primary (Lead) adapter in a Linked Display Adapter (LDA) + ///< chain + CTL_ADAPTER_PROPERTIES_FLAG_LDA_SECONDARY = CTL_BIT(2), ///< [out] Is Secondary (Linked) adapter in a Linked Display Adapter (LDA) + ///< chain + CTL_ADAPTER_PROPERTIES_FLAG_MAX = 0x80000000 + +} ctl_adapter_properties_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adapter Pci Bus, Device, Function +typedef struct _ctl_adapter_bdf_t +{ + uint8_t bus; ///< [out] PCI Bus Number + uint8_t device; ///< [out] PCI device number + uint8_t function; ///< [out] PCI function + +} ctl_adapter_bdf_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Device Adapter properties +typedef struct _ctl_device_adapter_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + void* pDeviceID; ///< [in,out] OS specific Device ID + uint32_t device_id_size; ///< [in] size of the device ID + ctl_device_type_t device_type; ///< [out] Device Type + ctl_supported_functions_flags_t supported_subfunction_flags;///< [out] Supported functions + uint64_t driver_version; ///< [out] Driver version + ctl_firmware_version_t firmware_version; ///< [out] Firmware version + uint32_t pci_vendor_id; ///< [out] PCI Vendor ID + uint32_t pci_device_id; ///< [out] PCI Device ID + uint32_t rev_id; ///< [out] PCI Revision ID + uint32_t num_eus_per_sub_slice; ///< [out] Number of EUs per sub-slice + uint32_t num_sub_slices_per_slice; ///< [out] Number of sub-slices per slice + uint32_t num_slices; ///< [out] Number of slices + char name[CTL_MAX_DEVICE_NAME_LEN]; ///< [out] Device name + ctl_adapter_properties_flags_t graphics_adapter_properties; ///< [out] Graphics Adapter Properties + uint32_t Frequency; ///< [out] Clock frequency for this device. Supported only for Version > 0 + uint16_t pci_subsys_id; ///< [out] PCI SubSys ID, Supported only for Version > 1 + uint16_t pci_subsys_vendor_id; ///< [out] PCI SubSys Vendor ID, Supported only for Version > 1 + ctl_adapter_bdf_t adapter_bdf; ///< [out] Pci Bus, Device, Function. Supported only for Version > 1 + char reserved[CTL_MAX_RESERVED_SIZE]; ///< [out] Reserved + +} ctl_device_adapter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief OperationType +typedef enum _ctl_operation_type_t +{ + CTL_OPERATION_TYPE_READ = 1, ///< Read operation + CTL_OPERATION_TYPE_WRITE = 2, ///< Write operation + CTL_OPERATION_TYPE_MAX + +} ctl_operation_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Generic Structure for Void* datatypes +typedef struct _ctl_generic_void_datatype_t +{ + void* pData; ///< [in,out]void pointer to memory + uint32_t size; ///< [in,out]size of the allocated memory + +} ctl_generic_void_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Generic Structure for Revision datatypes +typedef struct _ctl_revision_datatype_t +{ + uint8_t major_version; ///< [in,out]Major Version + uint8_t minor_version; ///< [in,out]Minor Version + uint8_t revision_version; ///< [in,out]Revision Version + +} ctl_revision_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Property Type flags +typedef uint32_t ctl_property_type_flags_t; +typedef enum _ctl_property_type_flag_t +{ + CTL_PROPERTY_TYPE_FLAG_DISPLAY = CTL_BIT(0), ///< Display type. Supported scenarios: Sharpness/gamma/CSC + CTL_PROPERTY_TYPE_FLAG_3D = CTL_BIT(1), ///< 3D type. Supported scenarios: All set calls via IGCL's 3D APIs + CTL_PROPERTY_TYPE_FLAG_MEDIA = CTL_BIT(2), ///< Media type. Supported scenarios: All set calls via IGCL's media APIs + CTL_PROPERTY_TYPE_FLAG_CORE = CTL_BIT(3), ///< For future: Core graphic event types like clocking, frequency etc. + CTL_PROPERTY_TYPE_FLAG_MAX = 0x80000000 + +} ctl_property_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Arguments related to wait for a property change function +typedef struct _ctl_wait_property_change_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_type_flags_t PropertyType; ///< [in] Type of the property + uint32_t TimeOutMilliSec; ///< [in][release] Time-out interval in milliseconds. Specify 0xFFFFFFFF if + ///< time-out is not desired + uint32_t EventMiscFlags; ///< [in][release] Event flags for future use + void* pReserved; ///< [in][release] Reserved for future use + uint64_t ReservedOutFlags; ///< [out] Reserved out argument for future use + +} ctl_wait_property_change_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display orientation (rotation) +typedef enum _ctl_display_orientation_t +{ + CTL_DISPLAY_ORIENTATION_0 = 0, ///< 0 Degree + CTL_DISPLAY_ORIENTATION_90 = 1, ///< 90 Degree + CTL_DISPLAY_ORIENTATION_180 = 2, ///< 180 Degree + CTL_DISPLAY_ORIENTATION_270 = 3, ///< 270 Degree + CTL_DISPLAY_ORIENTATION_MAX + +} ctl_display_orientation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Rectangle +typedef struct _ctl_rect_t +{ + int32_t Left; ///< [in,out] Left + int32_t Top; ///< [in,out] Top + int32_t Right; ///< [in,out] Right + int32_t Bottom; ///< [in,out] Bottom + +} ctl_rect_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Wait for a property change. Note that this is a blocking call +/// +/// @details +/// - Wait for a property change in display, 3d, media etc. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlWaitForPropertyChange( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_wait_property_change_args_t* pArgs ///< [in] Argument containing information about which property changes to + ///< listen for + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reserved function +/// +/// @details +/// - Reserved function +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlReservedCall( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_reserved_args_t* pArgs ///< [in] Argument containing information + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_base_interface_t +typedef struct _ctl_base_interface_t ctl_base_interface_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_t +typedef struct _ctl_property_range_info_t ctl_property_range_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_int_t +typedef struct _ctl_property_range_info_int_t ctl_property_range_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_range_info_uint_t +typedef struct _ctl_property_range_info_uint_t ctl_property_range_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_boolean_t +typedef struct _ctl_property_info_boolean_t ctl_property_info_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_boolean_t +typedef struct _ctl_property_boolean_t ctl_property_boolean_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_enum_t +typedef struct _ctl_property_info_enum_t ctl_property_info_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_enum_t +typedef struct _ctl_property_enum_t ctl_property_enum_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_float_t +typedef struct _ctl_property_info_float_t ctl_property_info_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_float_t +typedef struct _ctl_property_float_t ctl_property_float_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_int_t +typedef struct _ctl_property_info_int_t ctl_property_info_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_int_t +typedef struct _ctl_property_int_t ctl_property_int_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_info_uint_t +typedef struct _ctl_property_info_uint_t ctl_property_info_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_property_uint_t +typedef struct _ctl_property_uint_t ctl_property_uint_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_base_properties_t +typedef struct _ctl_base_properties_t ctl_base_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_application_id_t +typedef struct _ctl_application_id_t ctl_application_id_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_init_args_t +typedef struct _ctl_init_args_t ctl_init_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_reserved_args_t +typedef struct _ctl_reserved_args_t ctl_reserved_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_reserved_args_base_t +typedef struct _ctl_reserved_args_base_t ctl_reserved_args_base_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_unlock_capability_t +typedef struct _ctl_unlock_capability_t ctl_unlock_capability_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_runtime_path_args_t +typedef struct _ctl_runtime_path_args_t ctl_runtime_path_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_firmware_version_t +typedef struct _ctl_firmware_version_t ctl_firmware_version_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adapter_bdf_t +typedef struct _ctl_adapter_bdf_t ctl_adapter_bdf_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_device_adapter_properties_t +typedef struct _ctl_device_adapter_properties_t ctl_device_adapter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_generic_void_datatype_t +typedef struct _ctl_generic_void_datatype_t ctl_generic_void_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_revision_datatype_t +typedef struct _ctl_revision_datatype_t ctl_revision_datatype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_wait_property_change_args_t +typedef struct _ctl_wait_property_change_args_t ctl_wait_property_change_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_rect_t +typedef struct _ctl_rect_t ctl_rect_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming_caps_t +typedef struct _ctl_endurance_gaming_caps_t ctl_endurance_gaming_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming_t +typedef struct _ctl_endurance_gaming_t ctl_endurance_gaming_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_endurance_gaming2_t +typedef struct _ctl_endurance_gaming2_t ctl_endurance_gaming2_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adaptivesync_caps_t +typedef struct _ctl_adaptivesync_caps_t ctl_adaptivesync_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adaptivesync_getset_t +typedef struct _ctl_adaptivesync_getset_t ctl_adaptivesync_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_app_profiles_caps_t +typedef struct _ctl_3d_app_profiles_caps_t ctl_3d_app_profiles_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_app_profiles_t +typedef struct _ctl_3d_app_profiles_t ctl_3d_app_profiles_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_tier_details_t +typedef struct _ctl_3d_tier_details_t ctl_3d_tier_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_details_t +typedef struct _ctl_3d_feature_details_t ctl_3d_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_caps_t +typedef struct _ctl_3d_feature_caps_t ctl_3d_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_3d_feature_getset_t +typedef struct _ctl_3d_feature_getset_t ctl_3d_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_kmd_load_features_t +typedef struct _ctl_kmd_load_features_t ctl_kmd_load_features_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_display_timing_t +typedef struct _ctl_display_timing_t ctl_display_timing_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_display_properties_t +typedef struct _ctl_display_properties_t ctl_display_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_adapter_display_encoder_properties_t +typedef struct _ctl_adapter_display_encoder_properties_t ctl_adapter_display_encoder_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_filter_properties_t +typedef struct _ctl_sharpness_filter_properties_t ctl_sharpness_filter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_caps_t +typedef struct _ctl_sharpness_caps_t ctl_sharpness_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sharpness_settings_t +typedef struct _ctl_sharpness_settings_t ctl_sharpness_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_i2c_access_args_t +typedef struct _ctl_i2c_access_args_t ctl_i2c_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_i2c_access_pinpair_args_t +typedef struct _ctl_i2c_access_pinpair_args_t ctl_i2c_access_pinpair_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_aux_access_args_t +typedef struct _ctl_aux_access_args_t ctl_aux_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_caps_t +typedef struct _ctl_power_optimization_caps_t ctl_power_optimization_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_lrr_t +typedef struct _ctl_power_optimization_lrr_t ctl_power_optimization_lrr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_psr_t +typedef struct _ctl_power_optimization_psr_t ctl_power_optimization_psr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_dpst_t +typedef struct _ctl_power_optimization_dpst_t ctl_power_optimization_dpst_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_optimization_settings_t +typedef struct _ctl_power_optimization_settings_t ctl_power_optimization_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_set_brightness_t +typedef struct _ctl_set_brightness_t ctl_set_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_get_brightness_t +typedef struct _ctl_get_brightness_t ctl_get_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_color_primaries_t +typedef struct _ctl_pixtx_color_primaries_t ctl_pixtx_color_primaries_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pixel_format_t +typedef struct _ctl_pixtx_pixel_format_t ctl_pixtx_pixel_format_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_1dlut_config_t +typedef struct _ctl_pixtx_1dlut_config_t ctl_pixtx_1dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_matrix_config_t +typedef struct _ctl_pixtx_matrix_config_t ctl_pixtx_matrix_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_3dlut_sample_t +typedef struct _ctl_pixtx_3dlut_sample_t ctl_pixtx_3dlut_sample_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_3dlut_config_t +typedef struct _ctl_pixtx_3dlut_config_t ctl_pixtx_3dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_block_config_t +typedef struct _ctl_pixtx_block_config_t ctl_pixtx_block_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pipe_get_config_t +typedef struct _ctl_pixtx_pipe_get_config_t ctl_pixtx_pipe_get_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pixtx_pipe_set_config_t +typedef struct _ctl_pixtx_pipe_set_config_t ctl_pixtx_pipe_set_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_panel_descriptor_access_args_t +typedef struct _ctl_panel_descriptor_access_args_t ctl_panel_descriptor_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_retro_scaling_settings_t +typedef struct _ctl_retro_scaling_settings_t ctl_retro_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_retro_scaling_caps_t +typedef struct _ctl_retro_scaling_caps_t ctl_retro_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_scaling_caps_t +typedef struct _ctl_scaling_caps_t ctl_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_scaling_settings_t +typedef struct _ctl_scaling_settings_t ctl_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_lux_aggr_map_entry_t +typedef struct _ctl_lace_lux_aggr_map_entry_t ctl_lace_lux_aggr_map_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_lux_aggr_map_t +typedef struct _ctl_lace_lux_aggr_map_t ctl_lace_lux_aggr_map_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lace_config_t +typedef struct _ctl_lace_config_t ctl_lace_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_sw_psr_settings_t +typedef struct _ctl_sw_psr_settings_t ctl_sw_psr_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_intel_arc_sync_monitor_params_t +typedef struct _ctl_intel_arc_sync_monitor_params_t ctl_intel_arc_sync_monitor_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mux_properties_t +typedef struct _ctl_mux_properties_t ctl_mux_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_intel_arc_sync_profile_params_t +typedef struct _ctl_intel_arc_sync_profile_params_t ctl_intel_arc_sync_profile_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_edid_management_args_t +typedef struct _ctl_edid_management_args_t ctl_edid_management_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_get_set_custom_mode_args_t +typedef struct _ctl_get_set_custom_mode_args_t ctl_get_set_custom_mode_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_custom_src_mode_t +typedef struct _ctl_custom_src_mode_t ctl_custom_src_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_child_display_target_mode_t +typedef struct _ctl_child_display_target_mode_t ctl_child_display_target_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_combined_display_child_info_t +typedef struct _ctl_combined_display_child_info_t ctl_combined_display_child_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_combined_display_args_t +typedef struct _ctl_combined_display_args_t ctl_combined_display_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_display_info_t +typedef struct _ctl_genlock_display_info_t ctl_genlock_display_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_target_mode_list_t +typedef struct _ctl_genlock_target_mode_list_t ctl_genlock_target_mode_list_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_topology_t +typedef struct _ctl_genlock_topology_t ctl_genlock_topology_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_genlock_args_t +typedef struct _ctl_genlock_args_t ctl_genlock_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_vblank_ts_args_t +typedef struct _ctl_vblank_ts_args_t ctl_vblank_ts_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_lda_args_t +typedef struct _ctl_lda_args_t ctl_lda_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_dce_args_t +typedef struct _ctl_dce_args_t ctl_dce_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_engine_properties_t +typedef struct _ctl_engine_properties_t ctl_engine_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_engine_stats_t +typedef struct _ctl_engine_stats_t ctl_engine_stats_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_speed_t +typedef struct _ctl_fan_speed_t ctl_fan_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_temp_speed_t +typedef struct _ctl_fan_temp_speed_t ctl_fan_temp_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_speed_table_t +typedef struct _ctl_fan_speed_table_t ctl_fan_speed_table_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_properties_t +typedef struct _ctl_fan_properties_t ctl_fan_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_fan_config_t +typedef struct _ctl_fan_config_t ctl_fan_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_properties_t +typedef struct _ctl_freq_properties_t ctl_freq_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_range_t +typedef struct _ctl_freq_range_t ctl_freq_range_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_state_t +typedef struct _ctl_freq_state_t ctl_freq_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_freq_throttle_time_t +typedef struct _ctl_freq_throttle_time_t ctl_freq_throttle_time_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_super_resolution_info_t +typedef struct _ctl_video_processing_super_resolution_info_t ctl_video_processing_super_resolution_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_super_resolution_t +typedef struct _ctl_video_processing_super_resolution_t ctl_video_processing_super_resolution_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_noise_reduction_info_t +typedef struct _ctl_video_processing_noise_reduction_info_t ctl_video_processing_noise_reduction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_noise_reduction_t +typedef struct _ctl_video_processing_noise_reduction_t ctl_video_processing_noise_reduction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_adaptive_contrast_enhancement_info_t +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_info_t ctl_video_processing_adaptive_contrast_enhancement_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_adaptive_contrast_enhancement_t +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_t ctl_video_processing_adaptive_contrast_enhancement_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_standard_color_correction_info_t +typedef struct _ctl_video_processing_standard_color_correction_info_t ctl_video_processing_standard_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_standard_color_correction_t +typedef struct _ctl_video_processing_standard_color_correction_t ctl_video_processing_standard_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_total_color_correction_info_t +typedef struct _ctl_video_processing_total_color_correction_info_t ctl_video_processing_total_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_total_color_correction_t +typedef struct _ctl_video_processing_total_color_correction_t ctl_video_processing_total_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_details_t +typedef struct _ctl_video_processing_feature_details_t ctl_video_processing_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_caps_t +typedef struct _ctl_video_processing_feature_caps_t ctl_video_processing_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_video_processing_feature_getset_t +typedef struct _ctl_video_processing_feature_getset_t ctl_video_processing_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_properties_t +typedef struct _ctl_mem_properties_t ctl_mem_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_state_t +typedef struct _ctl_mem_state_t ctl_mem_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_mem_bandwidth_t +typedef struct _ctl_mem_bandwidth_t ctl_mem_bandwidth_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_telemetry_item_t +typedef struct _ctl_oc_telemetry_item_t ctl_oc_telemetry_item_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_control_info_t +typedef struct _ctl_oc_control_info_t ctl_oc_control_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_properties_t +typedef struct _ctl_oc_properties_t ctl_oc_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_oc_vf_pair_t +typedef struct _ctl_oc_vf_pair_t ctl_oc_vf_pair_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_psu_info_t +typedef struct _ctl_psu_info_t ctl_psu_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_telemetry_t +typedef struct _ctl_power_telemetry_t ctl_power_telemetry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_address_t +typedef struct _ctl_pci_address_t ctl_pci_address_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_speed_t +typedef struct _ctl_pci_speed_t ctl_pci_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_properties_t +typedef struct _ctl_pci_properties_t ctl_pci_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_pci_state_t +typedef struct _ctl_pci_state_t ctl_pci_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_properties_t +typedef struct _ctl_power_properties_t ctl_power_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_energy_counter_t +typedef struct _ctl_power_energy_counter_t ctl_power_energy_counter_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_sustained_limit_t +typedef struct _ctl_power_sustained_limit_t ctl_power_sustained_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_burst_limit_t +typedef struct _ctl_power_burst_limit_t ctl_power_burst_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_peak_limit_t +typedef struct _ctl_power_peak_limit_t ctl_power_peak_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_power_limits_t +typedef struct _ctl_power_limits_t ctl_power_limits_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_energy_threshold_t +typedef struct _ctl_energy_threshold_t ctl_energy_threshold_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Forward-declare ctl_temp_properties_t +typedef struct _ctl_temp_properties_t ctl_temp_properties_t; + + + +#if !defined(__GNUC__) +#pragma endregion // common +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region _3D +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature type +typedef enum _ctl_3d_feature_t +{ + CTL_3D_FEATURE_FRAME_PACING = 0, ///< Frame pacing. Contains generic enum type fields + CTL_3D_FEATURE_ENDURANCE_GAMING = 1, ///< Endurance gaming. Contains generic integer type fields. Value will be + ///< interpreted as the max FPS to be used when in DC mode globally or per + ///< application + CTL_3D_FEATURE_FRAME_LIMIT = 2, ///< Frame limit for games. Contains generic integer type fields. Value + ///< will be interpreted as the max FPS to be used independent of system + ///< power state + CTL_3D_FEATURE_ANISOTROPIC = 3, ///< ANISOTROPIC. Contains generic enum type fields + CTL_3D_FEATURE_CMAA = 4, ///< CMAA. Contains generic enum type fields + CTL_3D_FEATURE_TEXTURE_FILTERING_QUALITY = 5, ///< Texture filtering quality. Contains generic enum type fields + CTL_3D_FEATURE_ADAPTIVE_TESSELLATION = 6, ///< Adaptive tessellation quality. Contains generic integer type fields + CTL_3D_FEATURE_SHARPENING_FILTER = 7, ///< Sharpening Filter. Contains generic integer type fields + CTL_3D_FEATURE_MSAA = 8, ///< Msaa. Contains generic enum type fields + CTL_3D_FEATURE_GAMING_FLIP_MODES = 9, ///< Various Gaming flip modes like speed frame, smooth sync & force async + ///< flip. Contains generic enum type fields + CTL_3D_FEATURE_ADAPTIVE_SYNC_PLUS = 10, ///< Adaptive sync plus. Refer custom field ::ctl_adaptivesync_caps_t & + ///< ::ctl_adaptivesync_getset_t + CTL_3D_FEATURE_APP_PROFILES = 11, ///< Game Compatibility & Performance Profiles. Refer custom field + ///< ::ctl_3d_app_profiles_caps_t & ::ctl_3d_app_profiles_t + CTL_3D_FEATURE_APP_PROFILE_DETAILS = 12, ///< Game Profile Customization. Refer custom field ::ctl_3d_tier_details_t + CTL_3D_FEATURE_EMULATED_TYPED_64BIT_ATOMICS = 13, ///< Emulated Typed 64bit Atomics support in DG2 + CTL_3D_FEATURE_VRR_WINDOWED_BLT = 14, ///< VRR windowed blt. Control VRR for windowed mode game + CTL_3D_FEATURE_GLOBAL_OR_PER_APP = 15, ///< Set global settings or per application settings + CTL_3D_FEATURE_MAX + +} ctl_3d_feature_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature misc flags +typedef uint32_t ctl_3d_feature_misc_flags_t; +typedef enum _ctl_3d_feature_misc_flag_t +{ + CTL_3D_FEATURE_MISC_FLAG_DX11 = CTL_BIT(0), ///< Feature supported on DX11 + CTL_3D_FEATURE_MISC_FLAG_DX12 = CTL_BIT(1), ///< Feature supported on DX12 + CTL_3D_FEATURE_MISC_FLAG_VULKAN = CTL_BIT(2), ///< Feature supported on VULKAN + CTL_3D_FEATURE_MISC_FLAG_LIVE_CHANGE = CTL_BIT(3), ///< User can change feature live without restarting the game + CTL_3D_FEATURE_MISC_FLAG_MAX = 0x80000000 + +} ctl_3d_feature_misc_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Anisotropic values possible +typedef enum _ctl_3d_anisotropic_types_t +{ + CTL_3D_ANISOTROPIC_TYPES_APP_CHOICE = 0, ///< Application choice + CTL_3D_ANISOTROPIC_TYPES_2X = 2, ///< 2X + CTL_3D_ANISOTROPIC_TYPES_4X = 4, ///< 4X + CTL_3D_ANISOTROPIC_TYPES_8X = 8, ///< 8X + CTL_3D_ANISOTROPIC_TYPES_16X = 16, ///< 16X + CTL_3D_ANISOTROPIC_TYPES_MAX + +} ctl_3d_anisotropic_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Texture filtering values possible +typedef enum _ctl_3d_texture_filtering_quality_types_t +{ + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_PERFORMANCE = 0, ///< Performance + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_BALANCED = 1,///< Balanced + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_QUALITY = 2, ///< Quality + CTL_3D_TEXTURE_FILTERING_QUALITY_TYPES_MAX + +} ctl_3d_texture_filtering_quality_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frame pacing values possible +typedef enum _ctl_3d_frame_pacing_types_t +{ + CTL_3D_FRAME_PACING_TYPES_DISABLE = 0, ///< Disable + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_FRAME_NO_SMOOTHENING = 1, ///< Enable with scheduler without any frame smoothening + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_FRAME_MAX_SMOOTHENING = 2,///< Enable with scheduler with maximum smoothness + CTL_3D_FRAME_PACING_TYPES_ENABLE_MODE_COMPETITIVE_GAMING = 3, ///< Enable with scheduler in competitive gaming mode + CTL_3D_FRAME_PACING_TYPES_MAX + +} ctl_3d_frame_pacing_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming control possible +typedef enum _ctl_3d_endurance_gaming_control_t +{ + CTL_3D_ENDURANCE_GAMING_CONTROL_TURN_OFF = 0, ///< Endurance Gaming disable + CTL_3D_ENDURANCE_GAMING_CONTROL_TURN_ON = 1, ///< Endurance Gaming enable + CTL_3D_ENDURANCE_GAMING_CONTROL_AUTO = 2, ///< Endurance Gaming auto + CTL_3D_ENDURANCE_GAMING_CONTROL_MAX + +} ctl_3d_endurance_gaming_control_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming modes possible +typedef enum _ctl_3d_endurance_gaming_mode_t +{ + CTL_3D_ENDURANCE_GAMING_MODE_BETTER_PERFORMANCE = 0,///< Endurance Gaming better performance mode + CTL_3D_ENDURANCE_GAMING_MODE_BALANCED = 1, ///< Endurance Gaming balanced mode + CTL_3D_ENDURANCE_GAMING_MODE_MAXIMUM_BATTERY = 2, ///< Endurance Gaming maximum battery mode + CTL_3D_ENDURANCE_GAMING_MODE_MAX + +} ctl_3d_endurance_gaming_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Cmaa values possible +typedef enum _ctl_3d_cmaa_types_t +{ + CTL_3D_CMAA_TYPES_TURN_OFF = 0, ///< Turn off + CTL_3D_CMAA_TYPES_OVERRIDE_MSAA = 1, ///< Override MSAA + CTL_3D_CMAA_TYPES_ENHANCE_APPLICATION = 2, ///< Enhance Application + CTL_3D_CMAA_TYPES_MAX + +} ctl_3d_cmaa_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Tessellation +typedef enum _ctl_3d_adaptive_tessellation_types_t +{ + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_TURN_OFF = 0,///< Turn off + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_TURN_ON = 1, ///< Turn on + CTL_3D_ADAPTIVE_TESSELLATION_TYPES_MAX + +} ctl_3d_adaptive_tessellation_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sharpening filter values possible +typedef enum _ctl_3d_sharpening_filter_types_t +{ + CTL_3D_SHARPENING_FILTER_TYPES_TURN_OFF = 0, ///< Turn off + CTL_3D_SHARPENING_FILTER_TYPES_TURN_ON = 1, ///< Turn on + CTL_3D_SHARPENING_FILTER_TYPES_MAX + +} ctl_3d_sharpening_filter_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief MSAA values possible +typedef enum _ctl_3d_msaa_types_t +{ + CTL_3D_MSAA_TYPES_APP_CHOICE = 0, ///< Application choice + CTL_3D_MSAA_TYPES_DISABLED = 1, ///< Disabled. MSAA count 1 + CTL_3D_MSAA_TYPES_2X = 2, ///< 2X + CTL_3D_MSAA_TYPES_4X = 4, ///< 4X + CTL_3D_MSAA_TYPES_8X = 8, ///< 8X + CTL_3D_MSAA_TYPES_16X = 16, ///< 16X + CTL_3D_MSAA_TYPES_MAX + +} ctl_3d_msaa_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gaming flip modes +typedef uint32_t ctl_gaming_flip_mode_flags_t; +typedef enum _ctl_gaming_flip_mode_flag_t +{ + CTL_GAMING_FLIP_MODE_FLAG_APPLICATION_DEFAULT = CTL_BIT(0), ///< Application Default + CTL_GAMING_FLIP_MODE_FLAG_VSYNC_OFF = CTL_BIT(1), ///< Convert all sync flips to async on the next possible scanline. + CTL_GAMING_FLIP_MODE_FLAG_VSYNC_ON = CTL_BIT(2),///< Convert all async flips to sync flips. + CTL_GAMING_FLIP_MODE_FLAG_SMOOTH_SYNC = CTL_BIT(3), ///< Reduce tearing effect with async flips + CTL_GAMING_FLIP_MODE_FLAG_SPEED_FRAME = CTL_BIT(4), ///< Application unaware triple buffering + CTL_GAMING_FLIP_MODE_FLAG_CAPPED_FPS = CTL_BIT(5), ///< Limit the game FPS to panel RR + CTL_GAMING_FLIP_MODE_FLAG_MAX = 0x80000000 + +} ctl_gaming_flip_mode_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming caps +typedef struct _ctl_endurance_gaming_caps_t +{ + ctl_property_info_enum_t EGControlCaps; ///< [out] Endurance Gaming control capability + ctl_property_info_enum_t EGModeCaps; ///< [out] Endurance Gaming mode capability + +} ctl_endurance_gaming_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming Get/Set +typedef struct _ctl_endurance_gaming_t +{ + ctl_3d_endurance_gaming_control_t EGControl; ///< [in,out] Endurance Gaming control - Off/On/Auto + ctl_3d_endurance_gaming_mode_t EGMode; ///< [in,out] Endurance Gaming mode - Better Performance/Balanced/Maximum + ///< Battery + +} ctl_endurance_gaming_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Endurance Gaming version2 Get/Set +typedef struct _ctl_endurance_gaming2_t +{ + ctl_3d_endurance_gaming_control_t EGControl; ///< [in,out] Endurance Gaming control - Off/On/Auto + ctl_3d_endurance_gaming_mode_t EGMode; ///< [in,out] Endurance Gaming mode - Better Performance/Balanced/Maximum + ///< Battery + bool IsFPRequired; ///< [out] Is frame pacing required, dynamic state + double TargetFPS; ///< [out] Target FPS for frame pacing + double RefreshRate; ///< [out] Refresh rate used to calculate target fps + uint32_t Reserved[4]; ///< [out] Reserved fields + +} ctl_endurance_gaming2_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive sync plus caps +typedef struct _ctl_adaptivesync_caps_t +{ + bool AdaptiveBalanceSupported; ///< [out] Adaptive balance supported + ctl_property_info_float_t AdaptiveBalanceStrengthCaps; ///< [out] Strength of adaptive balance algorithm - min/max/steps/default + +} ctl_adaptivesync_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive sync plus +typedef struct _ctl_adaptivesync_getset_t +{ + bool AdaptiveSync; ///< [in,out] Adaptive sync. Note that in Windows, OS controls state of + ///< adaptive sync and which game gets the feature using it's own policies + bool AdaptiveBalance; ///< [in,out] Adaptive balance + bool AllowAsyncForHighFPS; ///< [in,out] Allow async flips when FPS is higher than max refresh rate of + ///< the panel + float AdaptiveBalanceStrength; ///< [in,out] Adaptive balance strength + +} ctl_adaptivesync_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game tier types +typedef uint32_t ctl_3d_tier_type_flags_t; +typedef enum _ctl_3d_tier_type_flag_t +{ + CTL_3D_TIER_TYPE_FLAG_COMPATIBILITY = CTL_BIT(0), ///< Compatibility Tier + CTL_3D_TIER_TYPE_FLAG_PERFORMANCE = CTL_BIT(1), ///< Performance Tier + CTL_3D_TIER_TYPE_FLAG_MAX = 0x80000000 + +} ctl_3d_tier_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game tiers +typedef uint32_t ctl_3d_tier_profile_flags_t; +typedef enum _ctl_3d_tier_profile_flag_t +{ + CTL_3D_TIER_PROFILE_FLAG_TIER_1 = CTL_BIT(0), ///< Tier 1 Profile + CTL_3D_TIER_PROFILE_FLAG_TIER_2 = CTL_BIT(1), ///< Tier 2 Profile + CTL_3D_TIER_PROFILE_FLAG_TIER_RECOMMENDED = CTL_BIT(30),///< Recommended Tier Profile. If set other tier values shouldn't be set + CTL_3D_TIER_PROFILE_FLAG_MAX = 0x80000000 + +} ctl_3d_tier_profile_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile Capabilities. Typically these remain the same across +/// games. +typedef struct _ctl_3d_app_profiles_caps_t +{ + ctl_3d_tier_type_flags_t SupportedTierTypes; ///< [out] Tier of interest for capability check + uint64_t Reserved; ///< [in,out] Reserved for future + +} ctl_3d_app_profiles_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile tiers +typedef struct _ctl_3d_app_profiles_t +{ + ctl_3d_tier_type_flag_t TierType; ///< [in] Tier type + ctl_3d_tier_profile_flags_t SupportedTierProfiles; ///< [out] Supported tier profiles bitmask + ctl_3d_tier_profile_flags_t DefaultEnabledTierProfiles; ///< [out] Default tiers which driver will enable if there is no user + ///< specific setting for global or per application + ctl_3d_tier_profile_flags_t CustomizationSupportedTierProfiles; ///< [out] Tiers supporting customization - reserved for future + ctl_3d_tier_profile_flags_t EnabledTierProfiles;///< [in,out] Tier profile(s) to be enabled/disabled in the case of a set + ///< call. For a get call this will return the currently enabled tiers + ctl_3d_tier_profile_flags_t CustomizationEnabledTierProfiles; ///< [in,out] Tier profile(s) which are customized. Caller shall call + ///< ::ctl_3d_tier_details_t to get specifics if any. + uint64_t Reserved; ///< [in,out] Reserved for future + +} ctl_3d_app_profiles_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Game Profile tiers details +typedef struct _ctl_3d_tier_details_t +{ + ctl_3d_tier_type_flag_t TierType; ///< [in] Tier type + ctl_3d_tier_profile_flag_t TierProfile; ///< [in] Tier profile(s) for get/set details + uint64_t Reserved[4]; ///< [in,out] Reserved for future + +} ctl_3d_tier_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Emulated Typed 64bit Atomics +typedef enum _ctl_emulated_typed_64bit_atomics_types_t +{ + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_DEFAULT = 0, ///< Default settings is based on workload/driver decision. + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_TURN_ON = 1, ///< Force Turn on + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_TURN_OFF = 2,///< Force Turn off + CTL_EMULATED_TYPED_64BIT_ATOMICS_TYPES_MAX + +} ctl_emulated_typed_64bit_atomics_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief VRR windowed BLT control possible. Reserved functionality +typedef enum _ctl_3d_vrr_windowed_blt_reserved_t +{ + CTL_3D_VRR_WINDOWED_BLT_RESERVED_AUTO = 0, ///< VRR windowed BLT auto + CTL_3D_VRR_WINDOWED_BLT_RESERVED_TURN_ON = 1, ///< VRR windowed BLT enable + CTL_3D_VRR_WINDOWED_BLT_RESERVED_TURN_OFF = 2, ///< VRR windowed BLT disable + CTL_3D_VRR_WINDOWED_BLT_RESERVED_MAX + +} ctl_3d_vrr_windowed_blt_reserved_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Global or per app values possible +typedef enum _ctl_3d_global_or_per_app_types_t +{ + CTL_3D_GLOBAL_OR_PER_APP_TYPES_NONE = 0, ///< none + CTL_3D_GLOBAL_OR_PER_APP_TYPES_PER_APP = 1, ///< Opt for per app settings + CTL_3D_GLOBAL_OR_PER_APP_TYPES_GLOBAL = 2, ///< Opt for global settings + CTL_3D_GLOBAL_OR_PER_APP_TYPES_MAX + +} ctl_3d_global_or_per_app_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature capability details which will have range/supported and +/// default values +typedef struct _ctl_3d_feature_details_t +{ + ctl_3d_feature_t FeatureType; ///< [out] 3D feature type + ctl_property_value_type_t ValueType; ///< [out] Type of value + ctl_property_info_t Value; ///< [out] Union of various type of values for 3D features. For enum types + ///< this can be anisotropic/frame pacing etc. This member is valid iff + ///< ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. Typically for a feature requiring custom + ///< struct, caller will know of it upfront and can provide the right size + ///< info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + bool PerAppSupport; ///< [out] Flag indicating whether the feature is supported per application + ///< or not + int64_t ConflictingFeatures; ///< [out] Mask of ::ctl_3d_feature_t values which can't be enabled along + ///< with the mentioned FeatureType. If this is 0, it meant the feature + ///< doesn't have any conflicts with other features + int16_t FeatureMiscSupport; ///< [out] 3D Feature Miscellaneous support flags. This will be based on + ///< ::ctl_3d_feature_misc_flags_t + int16_t Reserved; ///< [out] Reserved + int16_t Reserved1; ///< [out] Reserved + int16_t Reserved2; ///< [out] Reserved + +} ctl_3d_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature which are controllable +typedef struct _ctl_3d_feature_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSupportedFeatures; ///< [in,out] Number of elements in supported features array + ctl_3d_feature_details_t* pFeatureDetails; ///< [in,out] Array of feature details + +} ctl_3d_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief 3D feature for get/set +typedef struct _ctl_3d_feature_getset_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_3d_feature_t FeatureType; ///< [in] Features interested in + char* ApplicationName; ///< [in] Application name for which the property type is applicable. If + ///< this is an empty string then this will get/set global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + bool bSet; ///< [in] Set this if it's a set call + ctl_property_value_type_t ValueType; ///< [in] Type of value. Caller has to ensure it provides the right value + ///< type which decides how one read the union structure below + ctl_property_t Value; ///< [in,out] Union of various type of values for 3D features. For enum + ///< types this can be anisotropic/frame pacing etc. This member is valid + ///< iff ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. Typically for a feature requiring custom + ///< struct, caller will know of it upfront and cn provide the right size + ///< info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + +} ctl_3d_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Load KMD gaming features. Restricted function +typedef struct _ctl_kmd_load_features_t +{ + ctl_application_id_t ReservedFuncID; ///< [in] Unique ID for reserved/special function + bool bLoad; ///< [in] If set, will load known KMD features. If not set will reset known + ///< KMD features to default + int64_t SubsetFeatureMask; ///< [in,out] Mask indicating the subset of KMD features within + ///< ::ctl_3d_feature_t values. Default of 0 indicate all KMD features + char* ApplicationName; ///< [in] Application name for which the KMD properties are loaded for. If + ///< this is an empty string then this will load global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + int8_t CallerComponent; ///< [in] Caller component + int64_t Reserved[4]; ///< [in] Reserved field + +} ctl_kmd_load_features_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get 3D capabilities +/// +/// @details +/// - The application gets 3D properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeatureCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupported3DCapabilities( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_3d_feature_caps_t* pFeatureCaps ///< [in,out][release] 3D properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set 3D feature +/// +/// @details +/// - 3D feature details +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeature` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSet3DFeature( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_3d_feature_getset_t* pFeature ///< [in][release] 3D feature get/set parameter + ); + + +#if !defined(__GNUC__) +#pragma endregion // _3D +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region display +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a display output instance +typedef struct _ctl_display_output_handle_t *ctl_display_output_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a i2c pin-pair instance +typedef struct _ctl_i2c_pin_pair_handle_t *ctl_i2c_pin_pair_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Check Driver version +/// +/// @details +/// - The application checks driver version +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlCheckDriverVersion( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + ctl_version_info_t version_info ///< [in][release] Driver version info + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate devices +/// +/// @details +/// - The application enumerates all device adapters in the system +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateDevices( + ctl_api_handle_t hAPIHandle, ///< [in][release] Applications should pass the Control API handle returned + ///< by the CtlInit function + uint32_t* pCount, ///< [in,out][release] pointer to the number of device instances. If count + ///< is zero, then the api will update the value with the total + ///< number of drivers available. If count is non-zero, then the api will + ///< only retrieve the number of drivers. + ///< If count is larger than the number of drivers available, then the api + ///< will update the value with the correct number of drivers available. + ctl_device_adapter_handle_t* phDevices ///< [in,out][optional][release][range(0, *pCount)] array of driver + ///< instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate display outputs +/// +/// @details +/// - Enumerates display output capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateDisplayOutputs( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to control device adapter + uint32_t* pCount, ///< [in,out][release] pointer to the number of display output instances. + ///< If count is zero, then the api will update the value with the total + ///< number of outputs available. If count is non-zero, then the api will + ///< only retrieve the number of outputs. + ///< If count is larger than the number of drivers available, then the api + ///< will update the value with the correct number of drivers available. + ctl_display_output_handle_t* phDisplayOutputs ///< [in,out][optional][release][range(0, *pCount)] array of display output + ///< instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate I2C Pin Pairs +/// +/// @details +/// - Returns available list of I2C Pin-Pairs on a requested adapter +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "The incoming pointer pCount is null" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "The supplied Count is not equal to actual number of i2c pin-pair instances" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateI2CPinPairs( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] handle to device adapter + uint32_t* pCount, ///< [in,out][release] pointer to the number of i2c pin-pair instances. If + ///< count is zero, then the api will update the value with the total + ///< number of i2c pin-pair instances available. If count is non-zero and + ///< matches the avaialble number of pin-pairs, then the api will only + ///< return the avaialble number of i2c pin-pair instances in phI2cPinPairs. + ctl_i2c_pin_pair_handle_t* phI2cPinPairs ///< [out][optional][release][range(0, *pCount)] array of i2c pin pair + ///< instance handles. Need to be allocated by Caller when supplying the + ///< *pCount > 0. + ///< If Count is not equal to actual number of i2c pin-pair instances, it + ///< will return CTL_RESULT_ERROR_INVALID_SIZE. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief OS specific Display identifiers +typedef union _ctl_os_display_encoder_identifier_t +{ + uint32_t WindowsDisplayEncoderID; ///< [out] Windows OS Display encoder ID + ctl_generic_void_datatype_t DisplayEncoderID; ///< [out] Display encoder ID for non-windows OS + +} ctl_os_display_encoder_identifier_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various display types +typedef enum _ctl_display_output_types_t +{ + CTL_DISPLAY_OUTPUT_TYPES_INVALID = 0, ///< Invalid + CTL_DISPLAY_OUTPUT_TYPES_DISPLAYPORT = 1, ///< DisplayPort + CTL_DISPLAY_OUTPUT_TYPES_HDMI = 2, ///< HDMI + CTL_DISPLAY_OUTPUT_TYPES_DVI = 3, ///< DVI + CTL_DISPLAY_OUTPUT_TYPES_MIPI = 4, ///< MIPI + CTL_DISPLAY_OUTPUT_TYPES_CRT = 5, ///< CRT + CTL_DISPLAY_OUTPUT_TYPES_MAX + +} ctl_display_output_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported output bits per color (bpc) bitmasks +typedef uint32_t ctl_output_bpc_flags_t; +typedef enum _ctl_output_bpc_flag_t +{ + CTL_OUTPUT_BPC_FLAG_6BPC = CTL_BIT(0), ///< [out] Is 6bpc supported + CTL_OUTPUT_BPC_FLAG_8BPC = CTL_BIT(1), ///< [out] Is 8bpc supported + CTL_OUTPUT_BPC_FLAG_10BPC = CTL_BIT(2), ///< [out] Is 10bpc supported + CTL_OUTPUT_BPC_FLAG_12BPC = CTL_BIT(3), ///< [out] Is 12bpc supported + CTL_OUTPUT_BPC_FLAG_MAX = 0x80000000 + +} ctl_output_bpc_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display output features. This will indicate only the high level +/// capabilities +typedef uint32_t ctl_std_display_feature_flags_t; +typedef enum _ctl_std_display_feature_flag_t +{ + CTL_STD_DISPLAY_FEATURE_FLAG_HDCP = CTL_BIT(0), ///< [out] Is HDCP supported + CTL_STD_DISPLAY_FEATURE_FLAG_HD_AUDIO = CTL_BIT(1), ///< [out] Is HD Audio supported + CTL_STD_DISPLAY_FEATURE_FLAG_PSR = CTL_BIT(2), ///< [out] Is VESA PSR supported + CTL_STD_DISPLAY_FEATURE_FLAG_ADAPTIVESYNC_VRR = CTL_BIT(3), ///< [out] Is VESA Adaptive Sync or HDMI VRR supported + CTL_STD_DISPLAY_FEATURE_FLAG_VESA_COMPRESSION = CTL_BIT(4), ///< [out] Is display compression (VESA DSC) supported + CTL_STD_DISPLAY_FEATURE_FLAG_HDR = CTL_BIT(5), ///< [out] Is HDR supported + CTL_STD_DISPLAY_FEATURE_FLAG_HDMI_QMS = CTL_BIT(6), ///< [out] Is HDMI QMS supported + CTL_STD_DISPLAY_FEATURE_FLAG_MAX = 0x80000000 + +} ctl_std_display_feature_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Advanced Graphics Features provided by Intel Graphics Adapter. This +/// will indicate only the high level capabilities +typedef uint32_t ctl_intel_display_feature_flags_t; +typedef enum _ctl_intel_display_feature_flag_t +{ + CTL_INTEL_DISPLAY_FEATURE_FLAG_DPST = CTL_BIT(0), ///< [out] Is DPST supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_LACE = CTL_BIT(1), ///< [out] Is LACE supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_DRRS = CTL_BIT(2), ///< [out] Is DRRS supported + CTL_INTEL_DISPLAY_FEATURE_FLAG_MAX = 0x80000000 + +} ctl_intel_display_feature_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Attached Display Mux Type +typedef enum _ctl_attached_display_mux_type_t +{ + CTL_ATTACHED_DISPLAY_MUX_TYPE_NATIVE = 0, ///< [out] Native DP / HDMI + CTL_ATTACHED_DISPLAY_MUX_TYPE_THUNDERBOLT = 1, ///< [out] Thunderbolt + CTL_ATTACHED_DISPLAY_MUX_TYPE_TYPE_C = 2, ///< [out] USB Type C + CTL_ATTACHED_DISPLAY_MUX_TYPE_USB4 = 3, ///< [out] USB4 + CTL_ATTACHED_DISPLAY_MUX_TYPE_MAX + +} ctl_attached_display_mux_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Signal Standard +typedef enum _ctl_signal_standard_type_t +{ + CTL_SIGNAL_STANDARD_TYPE_UNKNOWN = 0, ///< [out] Unknown Signal Standard + CTL_SIGNAL_STANDARD_TYPE_CUSTOM = 1, ///< [out] Custom added timing + CTL_SIGNAL_STANDARD_TYPE_DMT = 2, ///< [out] DMT timing + CTL_SIGNAL_STANDARD_TYPE_GTF = 3, ///< [out] GTF Timing + CTL_SIGNAL_STANDARD_TYPE_CVT = 4, ///< [out] CVT Timing + CTL_SIGNAL_STANDARD_TYPE_CTA = 5, ///< [out] CTA Timing + CTL_SIGNAL_STANDARD_TYPE_MAX + +} ctl_signal_standard_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Protocol Converter Location +typedef uint32_t ctl_protocol_converter_location_flags_t; +typedef enum _ctl_protocol_converter_location_flag_t +{ + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_ONBOARD = CTL_BIT(0), ///< [out] OnBoard Protocol Converter + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_EXTERNAL = CTL_BIT(1), ///< [out] External Dongle + CTL_PROTOCOL_CONVERTER_LOCATION_FLAG_MAX = 0x80000000 + +} ctl_protocol_converter_location_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief [out] Display Output configuration related flags which indicate how +/// the output pixel stream drive the panel +typedef uint32_t ctl_display_config_flags_t; +typedef enum _ctl_display_config_flag_t +{ + CTL_DISPLAY_CONFIG_FLAG_DISPLAY_ACTIVE = CTL_BIT(0),///< [out] DisplayActive 0: InActive 1: Active + CTL_DISPLAY_CONFIG_FLAG_DISPLAY_ATTACHED = CTL_BIT(1), ///< [out] DisplayAttached.This Bit indicates if any dongle/display/hub is + ///< attached to the encoder. 0: Not Attached 1: Attached + CTL_DISPLAY_CONFIG_FLAG_IS_DONGLE_CONNECTED_TO_ENCODER = CTL_BIT(2),///< [out] This BIT will be set if a dongle/hub/onboard protocol converter + ///< , is attached to the encoder + CTL_DISPLAY_CONFIG_FLAG_DITHERING_ENABLED = CTL_BIT(3), ///< [out] This BIT will be set if dithering is enabled on the encoder + CTL_DISPLAY_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_display_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief [out] Encoder configuration related flags which indicate how the +/// output pixel stream drive the panel +typedef uint32_t ctl_encoder_config_flags_t; +typedef enum _ctl_encoder_config_flag_t +{ + CTL_ENCODER_CONFIG_FLAG_INTERNAL_DISPLAY = CTL_BIT(0), ///< [out] Internal connection or not + CTL_ENCODER_CONFIG_FLAG_VESA_TILED_DISPLAY = CTL_BIT(1),///< [out] VESA DisplayID based tiled display which is driven by either + ///< multiple physical connections (DisplayPort SST) or virtual streams + ///< (DisplayPort MST) + CTL_ENCODER_CONFIG_FLAG_TYPEC_CAPABLE = CTL_BIT(2), ///< [out] This is set if encoder supports type c display + CTL_ENCODER_CONFIG_FLAG_TBT_CAPABLE = CTL_BIT(3), ///< [out] This is set if encoder supports Thunderbolt display + CTL_ENCODER_CONFIG_FLAG_DITHERING_SUPPORTED = CTL_BIT(4), ///< [out] This BIT will be set if encoder supports dithering + CTL_ENCODER_CONFIG_FLAG_VIRTUAL_DISPLAY = CTL_BIT(5), ///< [out] This BIT will be set if this is a virtual display.Hardware based + ///< features will not be applicable to this display.For collage display + ///< this will be set for the virtual output created by driver. For split + ///< display this will be set for the virtual split displays created out of + ///< one single physical display + CTL_ENCODER_CONFIG_FLAG_HIDDEN_DISPLAY = CTL_BIT(6),///< [out] This BIT will be set if display is hidden from OS + CTL_ENCODER_CONFIG_FLAG_COLLAGE_DISPLAY = CTL_BIT(7), ///< [out] This BIT will be set if this is a collage display + CTL_ENCODER_CONFIG_FLAG_SPLIT_DISPLAY = CTL_BIT(8), ///< [out] This BIT will be set if this is a split display + CTL_ENCODER_CONFIG_FLAG_COMPANION_DISPLAY = CTL_BIT(9), ///< [out] This BIT will be set if this is a companion display + CTL_ENCODER_CONFIG_FLAG_MGPU_COLLAGE_DISPLAY = CTL_BIT(10), ///< [out] This BIT will be set if this is a Multi GPU collage display + CTL_ENCODER_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_encoder_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Timing +typedef struct _ctl_display_timing_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t PixelClock; ///< [out] Pixel Clock in Hz + uint32_t HActive; ///< [out] Horizontal Active + uint32_t VActive; ///< [out] Vertical Active + uint32_t HTotal; ///< [out] Horizontal Total + uint32_t VTotal; ///< [out] Vertical Total + uint32_t HBlank; ///< [out] Horizontal Blank + uint32_t VBlank; ///< [out] Vertical Blank + uint32_t HSync; ///< [out] Horizontal Blank + uint32_t VSync; ///< [out] Vertical Blank + float RefreshRate; ///< [out] Refresh Rate + ctl_signal_standard_type_t SignalStandard; ///< [out] Signal Standard + uint8_t VicId; ///< [out] VIC ID for CTA timings + +} ctl_display_timing_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief This structure will contain the properties of the display currently +/// attached to the encoder. +typedef struct _ctl_display_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_os_display_encoder_identifier_t Os_display_encoder_handle; ///< [out] OS specific Display ID + ctl_display_output_types_t Type; ///< [out] Device Type from display HW stand point. If a DisplayPort + ///< protocol converter is involved, this will indicate it's DisplayPort. + ///< The protocol converter's output will be available from + ///< ProtocolConverterOutput field + ctl_attached_display_mux_type_t AttachedDisplayMuxType; ///< [out] Attached Display Mux Type + ctl_display_output_types_t ProtocolConverterOutput; ///< [out] Protocol output type which can be used if config flags indicate + ///< it's a protocol converter. If it's not a protocol converter this will + ///< be set to CTL_DISPLAY_OUTPUT_TYPES_INVALID + ctl_revision_datatype_t SupportedSpec; ///< [out] Supported industry spec version. + ctl_output_bpc_flags_t SupportedOutputBPCFlags; ///< [out] Supported output bits per color. Refer ::ctl_output_bpc_flag_t. + ///< This is independent of RGB or YCbCr output.This is the max BPC + ///< supported.BPC will vary per mode based on restrictions like bandwidth + ///< and monitor support + ctl_protocol_converter_location_flags_t ProtocolConverterType; ///< [out] Currently Active Protocol Converter. Refer + ///< ::ctl_protocol_converter_location_flag_t + ctl_display_config_flags_t DisplayConfigFlags; ///< [out] Output configuration related flags which indicate how the output + ///< pixel stream drive the panel. Refer ::ctl_display_config_flag_t + ctl_std_display_feature_flags_t FeatureEnabledFlags;///< [out] Enabled Display features.Refer ::ctl_std_display_feature_flag_t. + ctl_std_display_feature_flags_t FeatureSupportedFlags; ///< [out] Display Supported feature.Refer ::ctl_std_display_feature_flag_t + ctl_intel_display_feature_flags_t AdvancedFeatureEnabledFlags; ///< [out] Enabled advanced feature.Refer + ///< ::ctl_intel_display_feature_flag_t. + ctl_intel_display_feature_flags_t AdvancedFeatureSupportedFlags;///< [out] Supported advanced feature.Refer + ///< ::ctl_intel_display_feature_flag_t. + ctl_display_timing_t Display_Timing_Info; ///< [out] Applied Timing on the Display + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_display_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adapter's display encoder properties +typedef struct _ctl_adapter_display_encoder_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_os_display_encoder_identifier_t Os_display_encoder_handle; ///< [out] OS specific Display ID + ctl_display_output_types_t Type; ///< [out] Device Type from display HW stand point. If a DisplayPort + ///< protocol converter is involved, this will indicate it's DisplayPort. + ///< The protocol converter's output will be available from + ///< ProtocolConverterOutput field + bool IsOnBoardProtocolConverterOutputPresent; ///< [out] Protocol output type which can be used if it's a protocol + ///< converter. If it's not a protocol converter this will be set to + ///< CTL_DISPLAY_OUTPUT_TYPES_INVALID + ctl_revision_datatype_t SupportedSpec; ///< [out] Supported industry spec version + ctl_output_bpc_flags_t SupportedOutputBPCFlags; ///< [out] Supported output bits per color. Refer ::ctl_output_bpc_flag_t. + ///< This is independent of RGB or YCbCr output.This is the max BPC + ///< supported.BPC will vary per mode based on restrictions like bandwidth + ///< and monitor support + ctl_encoder_config_flags_t EncoderConfigFlags; ///< [out] Output configuration related flags which indicate how the output + ///< pixel stream drive the panel. Refer ::ctl_encoder_config_flag_t + ///< Note: + ///< Virtual = 1: This indicates that its a software display. Hardware + ///< based features will not be applicable to this display. + ///< Collage=1,Virtual=1: Indicates the fake display output created by + ///< driver which has the combined resolution of multiple physical displays + ///< involved in collage configuration + ///< Collage=1,Virtual=0: Indicates the child physical displays involved + ///< in a collage configuration. These are real physical outputs + ///< Split=1,Virtual=1 : Indicates the fake display output created by + ///< driver which occupies a portion of a real physical display + ///< Split=1,Virtual=0 : Indicates the physical display which got split + ///< to form multiple split displays + ///< Split=1,Collage=1 : Invalid combination + ///< MgpuCollage=1,Collage=1,Virtual=1: Indicates the fake display + ///< output created by driver which has the combined resolution of multiple + ///< physical displays spread across multiple GPUs involved in Multi-GPU + ///< collage configuration + ///< MgpuCollage=1,Collage=1,Virtual=0: Indicates the child physical + ///< displays involved in a Multi-GPU collage configuration. These are real + ///< physical outputs + ctl_std_display_feature_flags_t FeatureSupportedFlags; ///< [out] Adapter Supported feature flags. Refer + ///< ::ctl_std_display_feature_flag_t + ctl_intel_display_feature_flags_t AdvancedFeatureSupportedFlags;///< [out] Advanced Features Supported by the Adapter. Refer + ///< ::ctl_intel_display_feature_flag_t + uint32_t ReservedFields[16]; ///< [out] Reserved field of 60 bytes + +} ctl_adapter_display_encoder_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Device Properties +/// +/// @details +/// - The application gets device properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetDeviceProperties( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to control device adapter + ctl_device_adapter_properties_t* pProperties ///< [in,out][release] Query result for device properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Display Properties +/// +/// @details +/// - The application gets display properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetDisplayProperties( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_display_properties_t* pProperties ///< [in,out][release] Query result for display properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Adapter Display encoder Properties +/// +/// @details +/// - The application gets the graphic adapters display encoder properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetAdaperDisplayEncoderProperties( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_adapter_display_encoder_properties_t* pProperties ///< [in,out][release] Query result for adapter display encoder properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Level0 Device handle +/// +/// @details +/// - The application gets OneAPI Level0 Device handles +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pZeDevice` +/// + `nullptr == hInstance` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetZeDevice( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + void* pZeDevice, ///< [out][release] ze_device handle + void** hInstance ///< [out][release] Module instance which caller can use to get export + ///< functions directly + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various sharpness filter types +typedef uint32_t ctl_sharpness_filter_type_flags_t; +typedef enum _ctl_sharpness_filter_type_flag_t +{ + CTL_SHARPNESS_FILTER_TYPE_FLAG_NON_ADAPTIVE = CTL_BIT(0), ///< Non-adaptive sharpness + CTL_SHARPNESS_FILTER_TYPE_FLAG_ADAPTIVE = CTL_BIT(1), ///< Adaptive sharpness + CTL_SHARPNESS_FILTER_TYPE_FLAG_MAX = 0x80000000 + +} ctl_sharpness_filter_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sharpness filter properties +typedef struct _ctl_sharpness_filter_properties_t +{ + ctl_sharpness_filter_type_flags_t FilterType; ///< [out] Filter type. Refer ::ctl_sharpness_filter_type_flag_t + ctl_property_range_info_t FilterDetails; ///< [out] Min, max & step size information + +} ctl_sharpness_filter_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Various sharpness filter types +typedef struct _ctl_sharpness_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_sharpness_filter_type_flags_t SupportedFilterFlags; ///< [out] Supported sharpness filters for a given display output. Refer + ///< ::ctl_sharpness_filter_type_flag_t + uint8_t NumFilterTypes; ///< [out] Number of elements in filter properties array + ctl_sharpness_filter_properties_t* pFilterProperty; ///< [in,out] Array of filter properties structure describing supported + ///< filter capabilities. Caller should provide a pre-allocated memory for + ///< this. + +} ctl_sharpness_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Current sharpness setting +typedef struct _ctl_sharpness_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enable; ///< [in,out] Current or new state of sharpness setting + ctl_sharpness_filter_type_flags_t FilterType; ///< [in,out] Current or new filter to be set. Refer + ///< ::ctl_sharpness_filter_type_flag_t + float Intensity; ///< [in,out] Setting intensity to be applied + +} ctl_sharpness_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Sharpness capability +/// +/// @details +/// - Returns sharpness capability +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSharpnessCaps( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_caps_t* pSharpnessCaps ///< [in,out][release] Query result for sharpness capability + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Sharpness setting +/// +/// @details +/// - Returns current sharpness settings +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetCurrentSharpness( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_settings_t* pSharpnessSettings ///< [in,out][release] Query result for sharpness current settings + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Sharpness setting +/// +/// @details +/// - Set current sharpness settings +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSharpnessSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetCurrentSharpness( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sharpness_settings_t* pSharpnessSettings ///< [in][release] Set sharpness current settings + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_I2C_MAX_DATA_SIZE +/// @brief I2C Maximum data size +#define CTL_I2C_MAX_DATA_SIZE 0x0080 +#endif // CTL_I2C_MAX_DATA_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C Access Args input Flags bitmasks +typedef uint32_t ctl_i2c_flags_t; +typedef enum _ctl_i2c_flag_t +{ + CTL_I2C_FLAG_ATOMICI2C = CTL_BIT(0), ///< Force Atomic I2C. + CTL_I2C_FLAG_1BYTE_INDEX = CTL_BIT(1), ///< 1-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_FLAG_2BYTE_INDEX = CTL_BIT(2), ///< 2-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_FLAG_4BYTE_INDEX = CTL_BIT(3), ///< 4-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_FLAG_SPEED_SLOW = CTL_BIT(4), ///< If no Speed Flag is set, defaults to Best Option possible. + CTL_I2C_FLAG_SPEED_FAST = CTL_BIT(5), ///< If no Speed Flag is set, defaults to Best Option possible. + CTL_I2C_FLAG_SPEED_BIT_BASH = CTL_BIT(6), ///< Uses Slower access using SW bit bashing method. If no Speed Flag is + ///< set, defaults to Best Option possible. + CTL_I2C_FLAG_MAX = 0x80000000 + +} ctl_i2c_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C access arguments +typedef struct _ctl_i2c_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t DataSize; ///< [in,out] Valid data size + uint32_t Address; ///< [in] Address to read or write + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write, for Write operation, App + ///< needs to run with admin privileges + uint32_t Offset; ///< [in] Offset + ctl_i2c_flags_t Flags; ///< [in] I2C Flags. Refer ::ctl_i2c_flag_t + uint64_t RAD; ///< [in] RAD, For Future use, to be used for branch devices, Interface + ///< will be provided to get RAD + uint8_t Data[CTL_I2C_MAX_DATA_SIZE]; ///< [in,out] Data array + +} ctl_i2c_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C Access +/// +/// @details +/// - Interface to access I2C using display handle as identifier. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pI2cAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid I2C data size" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlI2CAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_i2c_access_args_t* pI2cAccessArgs ///< [in,out] I2c access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C Access on PinPair Args input Flags bitmasks +typedef uint32_t ctl_i2c_pinpair_flags_t; +typedef enum _ctl_i2c_pinpair_flag_t +{ + CTL_I2C_PINPAIR_FLAG_ATOMICI2C = CTL_BIT(0), ///< Force Atomic I2C. + CTL_I2C_PINPAIR_FLAG_1BYTE_INDEX = CTL_BIT(1), ///< 1-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_PINPAIR_FLAG_2BYTE_INDEX = CTL_BIT(2), ///< 2-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_PINPAIR_FLAG_4BYTE_INDEX = CTL_BIT(3), ///< 4-byte Indexed operation. If no Index Size flag set, decided based on + ///< Offset Value. + CTL_I2C_PINPAIR_FLAG_SPEED_SLOW = CTL_BIT(4), ///< If no Speed Flag is set, defaults to Best Option possible. + CTL_I2C_PINPAIR_FLAG_SPEED_FAST = CTL_BIT(5), ///< If no Speed Flag is set, defaults to Best Option possible. + CTL_I2C_PINPAIR_FLAG_SPEED_BIT_BASH = CTL_BIT(6), ///< Uses Slower access using SW bit bashing method. If no Speed Flag is + ///< set, defaults to Best Option possible. + CTL_I2C_PINPAIR_FLAG_MAX = 0x80000000 + +} ctl_i2c_pinpair_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C access on Pin Pair arguments +typedef struct _ctl_i2c_access_pinpair_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t DataSize; ///< [in,out] Valid data size + uint32_t Address; ///< [in] Address to read or write + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write, for Write operation, App + ///< needs to run with admin privileges + uint32_t Offset; ///< [in] Offset + ctl_i2c_pinpair_flags_t Flags; ///< [in] I2C Flags. Refer ::ctl_i2c_pinpair_flag_t + uint8_t Data[CTL_I2C_MAX_DATA_SIZE]; ///< [in,out] Data array + uint32_t ReservedFields[4]; ///< [in] Reserved for future use, must be set to Zero. + +} ctl_i2c_access_pinpair_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief I2C Access On Pin Pair +/// +/// @details +/// - Interface to access I2C using pin-pair handle as identifier. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hI2cPinPair` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pI2cAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid I2C data size" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid Args passed" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_HANDLE - "Invalid or Null handle passed" +/// - ::CTL_RESULT_ERROR_EXTERNAL_DISPLAY_ATTACHED - "Write to Address not allowed when Display is connected" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlI2CAccessOnPinPair( + ctl_i2c_pin_pair_handle_t hI2cPinPair, ///< [in] Handle to I2C pin pair. + ctl_i2c_access_pinpair_args_t* pI2cAccessArgs ///< [in,out] I2c access arguments. + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_AUX_MAX_DATA_SIZE +/// @brief Aux Maximum data size +#define CTL_AUX_MAX_DATA_SIZE 132 +#endif // CTL_AUX_MAX_DATA_SIZE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief AUX Flags bitmasks +typedef uint32_t ctl_aux_flags_t; +typedef enum _ctl_aux_flag_t +{ + CTL_AUX_FLAG_NATIVE_AUX = CTL_BIT(0), ///< For Native AUX operation + CTL_AUX_FLAG_I2C_AUX = CTL_BIT(1), ///< For I2C AUX operation + CTL_AUX_FLAG_I2C_AUX_MOT = CTL_BIT(2), ///< For I2C AUX MOT operation + CTL_AUX_FLAG_MAX = 0x80000000 + +} ctl_aux_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief AUX access arguments +typedef struct _ctl_aux_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write, for Write operation, App + ///< needs to run with admin privileges + ctl_aux_flags_t Flags; ///< [in] Aux Flags. Refer ::ctl_aux_flag_t + uint32_t Address; ///< [in] Address to read or write + uint64_t RAD; ///< [in] RAD, For Future use, to be used for branch devices, Interface + ///< will be provided to get RAD + uint32_t PortID; ///< [in] Port ID, For Future use, to be used for SST tiled devices + uint32_t DataSize; ///< [in,out] Valid data size + uint8_t Data[CTL_AUX_MAX_DATA_SIZE]; ///< [in,out] Data array + +} ctl_aux_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Aux Access +/// +/// @details +/// - The application does Aux access, PSR needs to be disabled for AUX +/// call. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pAuxAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid AUX data size" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_INVALID_AUX_ACCESS_FLAG - "Invalid flag for AUX access" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlAUXAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_aux_access_args_t* pAuxAccessArgs ///< [in,out] Aux access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power saving features (Each individual feature's set & get call can be +/// called only once at a time) +typedef uint32_t ctl_power_optimization_flags_t; +typedef enum _ctl_power_optimization_flag_t +{ + CTL_POWER_OPTIMIZATION_FLAG_FBC = CTL_BIT(0), ///< Frame buffer compression + CTL_POWER_OPTIMIZATION_FLAG_PSR = CTL_BIT(1), ///< Panel self refresh + CTL_POWER_OPTIMIZATION_FLAG_DPST = CTL_BIT(2), ///< Display power saving technology (Panel technology dependent) + CTL_POWER_OPTIMIZATION_FLAG_LRR = CTL_BIT(3), ///< Low refresh rate (LRR/ALRR/UBRR), UBRR is supported only for IGCC and + ///< NDA clients. UBZRR and UBLRR both can not be enabled at the same time, + ///< only one can be enabled at a given time + CTL_POWER_OPTIMIZATION_FLAG_LACE = CTL_BIT(4), ///< Lighting Aware Contrast Enhancement + CTL_POWER_OPTIMIZATION_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief GPU/Panel/TCON dependent power optimization technology +typedef uint32_t ctl_power_optimization_dpst_flags_t; +typedef enum _ctl_power_optimization_dpst_flag_t +{ + CTL_POWER_OPTIMIZATION_DPST_FLAG_BKLT = CTL_BIT(0), ///< Intel DPST with Backlight control + CTL_POWER_OPTIMIZATION_DPST_FLAG_PANEL_CABC = CTL_BIT(1), ///< Panel TCON specific Content Adaptive Control mechanism + CTL_POWER_OPTIMIZATION_DPST_FLAG_OPST = CTL_BIT(2), ///< Intel OLED Power Saving Technology + CTL_POWER_OPTIMIZATION_DPST_FLAG_ELP = CTL_BIT(3), ///< TCON based Edge Luminance Profile + CTL_POWER_OPTIMIZATION_DPST_FLAG_EPSM = CTL_BIT(4), ///< Extra power saving mode + CTL_POWER_OPTIMIZATION_DPST_FLAG_APD = CTL_BIT(5), ///< Adaptive Pixel Dimming + CTL_POWER_OPTIMIZATION_DPST_FLAG_PIXOPTIX = CTL_BIT(6), ///< TCON+ based DPST like solution + CTL_POWER_OPTIMIZATION_DPST_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_dpst_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Source +typedef enum _ctl_power_source_t +{ + CTL_POWER_SOURCE_AC = 0, ///< Power Source AC + CTL_POWER_SOURCE_DC = 1, ///< Power Source DC + CTL_POWER_SOURCE_MAX + +} ctl_power_source_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Optimization Plan +typedef enum _ctl_power_optimization_plan_t +{ + CTL_POWER_OPTIMIZATION_PLAN_BALANCED = 0, ///< Balanced mode + CTL_POWER_OPTIMIZATION_PLAN_HIGH_PERFORMANCE = 1, ///< High Performance Mode + CTL_POWER_OPTIMIZATION_PLAN_POWER_SAVER = 2, ///< Power Saver Mode + CTL_POWER_OPTIMIZATION_PLAN_MAX + +} ctl_power_optimization_plan_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Type of low refresh rate feature +typedef uint32_t ctl_power_optimization_lrr_flags_t; +typedef enum _ctl_power_optimization_lrr_flag_t +{ + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR10 = CTL_BIT(0), ///< LRR 1.0 + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR20 = CTL_BIT(1), ///< LRR 2.0 + CTL_POWER_OPTIMIZATION_LRR_FLAG_LRR25 = CTL_BIT(2), ///< LRR 2.5 + CTL_POWER_OPTIMIZATION_LRR_FLAG_ALRR = CTL_BIT(3), ///< Autonomous LRR + CTL_POWER_OPTIMIZATION_LRR_FLAG_UBLRR = CTL_BIT(4), ///< User based low refresh rate + CTL_POWER_OPTIMIZATION_LRR_FLAG_UBZRR = CTL_BIT(5), ///< User based zero refresh rate + CTL_POWER_OPTIMIZATION_LRR_FLAG_MAX = 0x80000000 + +} ctl_power_optimization_lrr_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power optimization caps +typedef struct _ctl_power_optimization_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_flags_t SupportedFeatures; ///< [out] Supported power optimization features. Refer + ///< ::ctl_power_optimization_flag_t + +} ctl_power_optimization_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power optimization features +/// +/// @details +/// - Returns power optimization capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetPowerOptimizationCaps( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_caps_t* pPowerOptimizationCaps ///< [in,out][release] Query result for power optimization features + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief LRR detailed settings +typedef struct _ctl_power_optimization_lrr_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_lrr_flags_t SupportedLRRTypes; ///< [out] LRR type(s). Refer ::ctl_power_optimization_lrr_flag_t + ctl_power_optimization_lrr_flags_t CurrentLRRTypes; ///< [in,out] Current enabled LRR type(s) or the LRR type(s) to set to. + ///< Refer ::ctl_power_optimization_lrr_flag_t + bool bRequirePSRDisable; ///< [out] Require PSR disable for any change in the selected LRR feature. + ///< Caller can re-enable PSR once the respective LRR feature is + ///< enable/disabled. E.g. for UBRR based on platform this flag may not be + ///< set in which case caller doesn't need to do an explicit PSR disable + uint16_t LowRR; ///< [out] Lowest RR used for LRR functionality if known to source + +} ctl_power_optimization_lrr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSR detailed settings +typedef struct _ctl_power_optimization_psr_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t PSRVersion; ///< [in,out] A value of 1 means PSR1, 2 means PSR2 + bool FullFetchUpdate; ///< [in,out] Full fetch and update + +} ctl_power_optimization_psr_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief DPST detailed settings +typedef struct _ctl_power_optimization_dpst_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t MinLevel; ///< [out] Minimum supported aggressiveness level + uint8_t MaxLevel; ///< [out] Maximum supported aggressiveness level + uint8_t Level; ///< [in,out] Current aggressiveness level to be set + ctl_power_optimization_dpst_flags_t SupportedFeatures; ///< [out] Supported features + ctl_power_optimization_dpst_flags_t EnabledFeatures;///< [in,out] Features enabled or to be enabled. Fill only one feature for + ///< SET call + +} ctl_power_optimization_dpst_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature specific power optimization data +typedef union _ctl_power_optimization_feature_specific_info_t +{ + ctl_power_optimization_lrr_t LRRInfo; ///< [out] LRR info + ctl_power_optimization_psr_t PSRInfo; ///< [in,out] PSR info + ctl_power_optimization_dpst_t DPSTInfo; ///< [in,out] DPST info + +} ctl_power_optimization_feature_specific_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power optimization settings +typedef struct _ctl_power_optimization_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_optimization_plan_t PowerOptimizationPlan;///< [in] Power optimization power plan (max power/max perf/balanced) + ctl_power_optimization_flags_t PowerOptimizationFeature;///< [in] Power optimization feature interested in. Refer + ///< ::ctl_power_optimization_flag_t + bool Enable; ///< [in,out] Enable state + ctl_power_optimization_feature_specific_info_t FeatureSpecificData; ///< [in,out] Data specific to the feature caller is interested in + ctl_power_source_t PowerSource; ///< [in] AC/DC + +} ctl_power_optimization_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Brightness settings for SET call +typedef struct _ctl_set_brightness_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t TargetBrightness; ///< [in] The brightness level that the display need to transitioning to in + ///< milli-percentage. Range is 0-100000 (100%) + uint32_t SmoothTransitionTimeInMs; ///< [in] Transition Time for brightness to take effect in milli-seconds. + ///< If its 0 then it will be an immediate change. Maximum possible value + ///< is 1000ms. + uint32_t ReservedFields[4]; ///< [in] Reserved for future use + +} ctl_set_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Brightness settings for GET call +typedef struct _ctl_get_brightness_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t TargetBrightness; ///< [out] The brightness level that the display is currently transitioning + ///< to in milli-percentage. If not in a transition, this should equal the + ///< current brightness. Range is 0-100000 (100%) + uint32_t CurrentBrightness; ///< [out] The current brightness level of the display in milli-percentage + uint32_t ReservedFields[4]; ///< [out] Reserved for future use + +} ctl_get_brightness_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power optimization setting +/// +/// @details +/// - Returns power optimization setting for a specific feature +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG - "Unsupported PowerOptimizationFeature" +/// - ::CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST - "DPST is supported only in DC Mode" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetPowerOptimizationSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_settings_t* pPowerOptimizationSettings ///< [in,out][release] Power optimization data to be fetched + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Power optimization setting +/// +/// @details +/// - Set power optimization setting for a specific feature +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPowerOptimizationSettings` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_POWERFEATURE_OPTIMIZATION_FLAG - "Unsupported PowerOptimizationFeature" +/// - ::CTL_RESULT_ERROR_INVALID_POWERSOURCE_TYPE_FOR_DPST - "DPST is supported only in DC Mode" +/// - ::CTL_RESULT_ERROR_SET_FBC_FEATURE_NOT_SUPPORTED - "Set FBC Feature not supported" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetPowerOptimizationSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_power_optimization_settings_t* pPowerOptimizationSettings ///< [in][release] Power optimization data to be applied + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Brightness on companion display +/// +/// @details +/// - Set Brightness for a target display. Currently support is only for +/// companion display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSetBrightnessSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid Brightness data passed as argument" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE - "Display not active" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Currently Brightness API is supported only on companion display" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetBrightnessSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_set_brightness_t* pSetBrightnessSetting ///< [in][release] Brightness settings to be applied + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Brightness setting +/// +/// @details +/// - Get Brightness for a target display. Currently support is only for +/// companion display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetBrightnessSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ACTIVE - "Display not active" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Currently Brightness API is supported only on companion display" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetBrightnessSetting( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_get_brightness_t* pGetBrightnessSetting ///< [out][release] Brightness settings data to be fetched + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT +/// @brief Maximum number of samples per channel 1D LUT +#define CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT 8192 +#endif // CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixtx pipe set configuration flags bitmasks +typedef uint32_t ctl_pixtx_pipe_set_config_flags_t; +typedef enum _ctl_pixtx_pipe_set_config_flag_t +{ + CTL_PIXTX_PIPE_SET_CONFIG_FLAG_PERSIST_ACROSS_POWER_EVENTS = CTL_BIT(0),///< For maintaining persistance across power events + CTL_PIXTX_PIPE_SET_CONFIG_FLAG_MAX = 0x80000000 + +} ctl_pixtx_pipe_set_config_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation block types +typedef enum _ctl_pixtx_block_type_t +{ + CTL_PIXTX_BLOCK_TYPE_1D_LUT = 1, ///< Block type 1D LUT + CTL_PIXTX_BLOCK_TYPE_3D_LUT = 2, ///< Block type 3D LUT + CTL_PIXTX_BLOCK_TYPE_3X3_MATRIX = 3, ///< Block type 3x3 matrix + CTL_PIXTX_BLOCK_TYPE_3X3_MATRIX_AND_OFFSETS = 4,///< Block type 3x3 matrix and offsets + CTL_PIXTX_BLOCK_TYPE_MAX + +} ctl_pixtx_block_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation LUT sampling types +typedef enum _ctl_pixtx_lut_sampling_type_t +{ + CTL_PIXTX_LUT_SAMPLING_TYPE_UNIFORM = 0, ///< Uniform LUT sampling + CTL_PIXTX_LUT_SAMPLING_TYPE_NONUNIFORM = 1, ///< Non uniform LUT sampling, Required mainly in HDR mode + CTL_PIXTX_LUT_SAMPLING_TYPE_MAX + +} ctl_pixtx_lut_sampling_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configuration query types +typedef enum _ctl_pixtx_config_query_type_t +{ + CTL_PIXTX_CONFIG_QUERY_TYPE_CAPABILITY = 0, ///< Get complete pixel processing pipeline capability + CTL_PIXTX_CONFIG_QUERY_TYPE_CURRENT = 1, ///< Get the configuration set through last set call + CTL_PIXTX_CONFIG_QUERY_TYPE_MAX + +} ctl_pixtx_config_query_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configuration operation types +typedef enum _ctl_pixtx_config_opertaion_type_t +{ + CTL_PIXTX_CONFIG_OPERTAION_TYPE_RESTORE_DEFAULT = 1,///< Restore block by block or entire pipe line. Use NumBlocks = 0 to + ///< restore all. + CTL_PIXTX_CONFIG_OPERTAION_TYPE_SET_CUSTOM = 2, ///< Custom LUT or matrix can be set thorugh this option. + CTL_PIXTX_CONFIG_OPERTAION_TYPE_MAX + +} ctl_pixtx_config_opertaion_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation gamma encoding types +typedef enum _ctl_pixtx_gamma_encoding_type_t +{ + CTL_PIXTX_GAMMA_ENCODING_TYPE_SRGB = 0, ///< Gamma encoding SRGB + CTL_PIXTX_GAMMA_ENCODING_TYPE_REC709 = 1, ///< Gamma encoding REC709, Applicable for REC2020 as well + CTL_PIXTX_GAMMA_ENCODING_TYPE_ST2084 = 2, ///< Gamma encoding ST2084 + CTL_PIXTX_GAMMA_ENCODING_TYPE_HLG = 3, ///< Gamma encoding HLG + CTL_PIXTX_GAMMA_ENCODING_TYPE_LINEAR = 4, ///< Gamma encoding linear + CTL_PIXTX_GAMMA_ENCODING_TYPE_MAX + +} ctl_pixtx_gamma_encoding_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color space types +typedef enum _ctl_pixtx_color_space_t +{ + CTL_PIXTX_COLOR_SPACE_REC709 = 0, ///< Color space REC709 + CTL_PIXTX_COLOR_SPACE_REC2020 = 1, ///< Color space REC2020 + CTL_PIXTX_COLOR_SPACE_ADOBE_RGB = 2, ///< Color space AdobeRGB + CTL_PIXTX_COLOR_SPACE_P3_D65 = 3, ///< Color space P3_D65 + CTL_PIXTX_COLOR_SPACE_P3_DCI = 4, ///< Color space P3_DCI + CTL_PIXTX_COLOR_SPACE_P3_D60 = 5, ///< Color space P3_D60 + CTL_PIXTX_COLOR_SPACE_CUSTOM = 0xFFFF, ///< Color space custom, Refer ::ctl_pixtx_color_primaries_t for color + ///< primary details + CTL_PIXTX_COLOR_SPACE_MAX + +} ctl_pixtx_color_space_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color model types +typedef enum _ctl_pixtx_color_model_t +{ + CTL_PIXTX_COLOR_MODEL_RGB_FR = 0, ///< Color model RGB full range + CTL_PIXTX_COLOR_MODEL_RGB_LR = 1, ///< Color model RGB limited range + CTL_PIXTX_COLOR_MODEL_YCBCR_422_FR = 2, ///< Color model YCBCR 422 full range + CTL_PIXTX_COLOR_MODEL_YCBCR_422_LR = 3, ///< Color model YCBCR 422 limited range + CTL_PIXTX_COLOR_MODEL_YCBCR_420_FR = 4, ///< Color model YCBCR 420 full range + CTL_PIXTX_COLOR_MODEL_YCBCR_420_LR = 5, ///< Color model YCBCR 420 limited range + CTL_PIXTX_COLOR_MODEL_YCBCR_444_FR = 6, ///< Color model YCBCR 444 full range + CTL_PIXTX_COLOR_MODEL_YCBCR_444_LR = 7, ///< Color model YCBCR 444 limited range + CTL_PIXTX_COLOR_MODEL_MAX + +} ctl_pixtx_color_model_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation color primaries +typedef struct _ctl_pixtx_color_primaries_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double xR; ///< [out] CIE1931 x value with maximum red pixel value + double yR; ///< [out] CIE1931 y value with maximum red pixel value + double xG; ///< [out] CIE1931 x value with maximum green pixel value + double yG; ///< [out] CIE1931 y value with maximum green pixel value + double xB; ///< [out] CIE1931 x value with maximum blue pixel value + double yB; ///< [out] CIE1931 y value with maximum blue pixel value + double xW; ///< [out] CIE1931 x value with maximum white pixel value + double yW; ///< [out] CIE1931 y value with maximum white pixel value + +} ctl_pixtx_color_primaries_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pixel format +typedef struct _ctl_pixtx_pixel_format_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t BitsPerColor; ///< [out] Bits per color, It Will be 16 for FP16 case + bool IsFloat; ///< [out] Will be set for FP16 or other floating point encoding schemes + ctl_pixtx_gamma_encoding_type_t EncodingType; ///< [out] Encoding type + ctl_pixtx_color_space_t ColorSpace; ///< [out] Color space + ctl_pixtx_color_model_t ColorModel; ///< [out] Color model + ctl_pixtx_color_primaries_t ColorPrimaries; ///< [out] Color primaries, Used mainly for custom color space + double MaxBrightness; ///< [out] Maximum brightness of pixel values. If no input is given, + ///< default will be set to sRGB during set call. If panel capability is + ///< not known get call will default to sRGB. + double MinBrightness; ///< [out] Minimum brightness of pixel values + +} ctl_pixtx_pixel_format_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 1D LUT configuration +typedef struct _ctl_pixtx_1dlut_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_lut_sampling_type_t SamplingType; ///< [in,out] Blocks with non-uniform sampling capability support unifrom + ///< sampling also but not vice versa. + uint32_t NumSamplesPerChannel; ///< [in,out] Number of samples per channel. Resampled internally based on + ///< HW capability for uniformly sampled LUT.Maximum supported value is + ///< ::CTL_MAX_NUM_SAMPLES_PER_CHANNEL_1D_LUT Caller needs to use exact + ///< sampling position given in pSamplePositions for non-uniformly sampled + ///< LUTs. + uint32_t NumChannels; ///< [in,out] Number of channels, 1 for Grey scale LUT, 3 for RGB LUT + double* pSampleValues; ///< [in,out] Pointer to sample values, R array followed by G and B arrays + ///< in case of multi-channel LUT. Allocation size for pSampleValues should + ///< be NumSamplesPerChannel * NumChannels * sizeof(double) + double* pSamplePositions; ///< [out] LUT (same for all channels) to represent sampling positions for + ///< non-uniformly sampled LUTs.Can be NULL in case uniformly sampled LUTs + +} ctl_pixtx_1dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation matrix configuration +typedef struct _ctl_pixtx_matrix_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double PreOffsets[3]; ///< [in,out] Pre offsets + double PostOffsets[3]; ///< [in,out] Post offsets + double Matrix[3][3]; ///< [in,out] 3x3 Matrix + +} ctl_pixtx_matrix_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 3D LUT sample. Samples are converted to integer +/// based on underlying HW capabilities. Hence slight precision loss will +/// be observed while getting sample values. +typedef struct _ctl_pixtx_3dlut_sample_t +{ + double Red; ///< [in,out] Red output value + double Green; ///< [in,out] Green output value + double Blue; ///< [in,out] Blue output value + +} ctl_pixtx_3dlut_sample_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation 3D LUT configuration +typedef struct _ctl_pixtx_3dlut_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSamplesPerChannel; ///< [in,out] Number of samples per channel + ctl_pixtx_3dlut_sample_t* pSampleValues; ///< [in,out] Pointer to sample values, R in outer most loop followed by G + ///< and B + +} ctl_pixtx_3dlut_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation configuration +typedef union _ctl_pixtx_config_t +{ + ctl_pixtx_1dlut_config_t OneDLutConfig; ///< [in,out] 1D LUT configuration + ctl_pixtx_3dlut_config_t ThreeDLutConfig; ///< [in,out] 3D LUT configuration + ctl_pixtx_matrix_config_t MatrixConfig; ///< [in,out] Matrix configuration + +} ctl_pixtx_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation block configuration +typedef struct _ctl_pixtx_block_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t BlockId; ///< [in,out] Unique ID for each pixel processing block. Id for a block is + ///< fixed for a platform. + ctl_pixtx_block_type_t BlockType; ///< [in,out] Block type + ctl_pixtx_config_t Config; ///< [in,out] Configuration + +} ctl_pixtx_block_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pipe get configuration +typedef struct _ctl_pixtx_pipe_get_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_config_query_type_t QueryType; ///< [in] Query operation type + ctl_pixtx_pixel_format_t InputPixelFormat; ///< [out] Input pixel format + ctl_pixtx_pixel_format_t OutputPixelFormat; ///< [out] Output pixel format + uint32_t NumBlocks; ///< [out] Number of blocks + ctl_pixtx_block_config_t* pBlockConfigs; ///< [out] Pointer to specific configs + +} ctl_pixtx_pipe_get_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation pipe set configuration +typedef struct _ctl_pixtx_pipe_set_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pixtx_config_opertaion_type_t OpertaionType;///< [in] Set operation type + ctl_pixtx_pipe_set_config_flags_t Flags; ///< [in] Config flags. Refer ::ctl_pixtx_pipe_set_config_flag_t + uint32_t NumBlocks; ///< [in] Number of blocks + ctl_pixtx_block_config_t* pBlockConfigs; ///< [in,out] Array of block specific configs + +} ctl_pixtx_pipe_set_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation get pipe configuration +/// +/// @details +/// - The application does pixel transformation get pipe configuration +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPixTxGetConfigArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_GET_CONFIG_QUERY_TYPE - "Invalid query type" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID - "Invalid block id" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PIXTX_BLOCK_CONFIG_MEMORY - "Insufficient memery allocated for BlockConfigs" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_PIPE - "Invalid pipe for 3dlut" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_DATA - "Invalid 3dlut data" +/// - ::CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR - "3dlut not supported in HDR" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION - "Invalid 3dlut operation" +/// - ::CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL - "3dlut call unsuccessful" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPixelTransformationGetConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_pixtx_pipe_get_config_t* pPixTxGetConfigArgs///< [in,out] Pixel transformation get pipe configiguration arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Pixel transformation set pipe configuration +/// +/// @details +/// - The application does pixel transformation set pipe configuration +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPixTxSetConfigArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_SET_CONFIG_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_SET_CONFIG_NUMBER_OF_SAMPLES - "Invalid number of samples" +/// - ::CTL_RESULT_ERROR_INVALID_PIXTX_BLOCK_ID - "Invalid block id" +/// - ::CTL_RESULT_ERROR_PERSISTANCE_NOT_SUPPORTED - "Persistance not supported" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_PIPE - "Invalid pipe for 3dlut" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_DATA - "Invalid 3dlut data" +/// - ::CTL_RESULT_ERROR_3DLUT_NOT_SUPPORTED_IN_HDR - "3dlut not supported in HDR" +/// - ::CTL_RESULT_ERROR_3DLUT_INVALID_OPERATION - "Invalid 3dlut operation" +/// - ::CTL_RESULT_ERROR_3DLUT_UNSUCCESSFUL - "3dlut call unsuccessful" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPixelTransformationSetConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_pixtx_pipe_set_config_t* pPixTxSetConfigArgs///< [in,out] Pixel transformation set pipe configiguration arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Panel descriptor access arguments +typedef struct _ctl_panel_descriptor_access_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_operation_type_t OpType; ///< [in] Operation type, 1 for Read, 2 for Write. App needs to run with + ///< admin privileges for Write operation, Currently only Read operation is + ///< supported + uint32_t BlockNumber; ///< [in] Block number, Need to provide only if acccessing EDID + uint32_t DescriptorDataSize; ///< [in] Descriptor data size, Should be 0 for querying the size and + ///< should be DescriptorDataSize derived from query call otherwise + uint8_t* pDescriptorData; ///< [in,out] Panel descriptor data + +} ctl_panel_descriptor_access_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Panel Descriptor Access +/// +/// @details +/// - The application does EDID or Display ID access +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pPanelDescriptorAccessArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPanelDescriptorAccess( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_panel_descriptor_access_args_t* pPanelDescriptorAccessArgs ///< [in,out] Panel descriptor access arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retro Scaling Types +typedef uint32_t ctl_retro_scaling_type_flags_t; +typedef enum _ctl_retro_scaling_type_flag_t +{ + CTL_RETRO_SCALING_TYPE_FLAG_INTEGER = CTL_BIT(0), ///< Integer Scaling + CTL_RETRO_SCALING_TYPE_FLAG_NEAREST_NEIGHBOUR = CTL_BIT(1), ///< Nearest Neighbour Scaling + CTL_RETRO_SCALING_TYPE_FLAG_MAX = 0x80000000 + +} ctl_retro_scaling_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get Retro Scaling Type +typedef struct _ctl_retro_scaling_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Get; ///< [in][release] Set to true to get current scaling . Set to False to Set + ///< the scaling + bool Enable; ///< [in,out] State of the scaler + ctl_retro_scaling_type_flags_t RetroScalingType;///< [out] Requested retro scaling types. Refer + ///< ::ctl_retro_scaling_type_flag_t + +} ctl_retro_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Retro Scaling caps +typedef struct _ctl_retro_scaling_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_retro_scaling_type_flags_t SupportedRetroScaling; ///< [out] Supported retro scaling types + +} ctl_retro_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Supported Retro Scaling Types +/// +/// @details +/// - Returns supported retro scaling capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pRetroScalingCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedRetroScalingCapability( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + ctl_retro_scaling_caps_t* pRetroScalingCaps ///< [in,out][release] Query result for supported retro scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Retro Scaling +/// +/// @details +/// - Get or Set the status of retro scaling.This Api will do a physical +/// modeset resulting in flash on the screen +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetSetRetroScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetRetroScaling( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + ctl_retro_scaling_settings_t* pGetSetRetroScalingType ///< [in,out][release] Get or Set the retro scaling type + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Scaling Types +typedef uint32_t ctl_scaling_type_flags_t; +typedef enum _ctl_scaling_type_flag_t +{ + CTL_SCALING_TYPE_FLAG_IDENTITY = CTL_BIT(0), ///< No scaling is applied and display manages scaling itself when possible + CTL_SCALING_TYPE_FLAG_CENTERED = CTL_BIT(1), ///< Source is not scaled but place in the center of the target display + CTL_SCALING_TYPE_FLAG_STRETCHED = CTL_BIT(2), ///< Source is stretched to fit the target size + CTL_SCALING_TYPE_FLAG_ASPECT_RATIO_CENTERED_MAX = CTL_BIT(3), ///< The aspect ratio is maintained with the source centered + CTL_SCALING_TYPE_FLAG_CUSTOM = CTL_BIT(4), ///< None of the standard types match this .Additional parameters are + ///< required which should be set via a private driver interface + CTL_SCALING_TYPE_FLAG_MAX = 0x80000000 + +} ctl_scaling_type_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Scaling caps +typedef struct _ctl_scaling_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_scaling_type_flags_t SupportedScaling; ///< [out] Supported scaling types. Refer ::ctl_scaling_type_flag_t + +} ctl_scaling_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get Scaling type +typedef struct _ctl_scaling_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enable; ///< [in,out] State of the scaler + ctl_scaling_type_flags_t ScalingType; ///< [in,out] Requested scaling types. Refer ::ctl_scaling_type_flag_t + uint32_t CustomScalingX; ///< [in,out] Custom Scaling X resolution + uint32_t CustomScalingY; ///< [in,out] Custom Scaling Y resolution + bool HardwareModeSet; ///< [in] Flag to indicate hardware modeset should be done to apply the + ///< scaling.Setting this to true would result in a flash on the screen. If + ///< this flag is set to false , API will request the OS to do a virtual + ///< modeset , but the OS can ignore this request and do a hardware modeset + ///< in some instances + +} ctl_scaling_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Supported Scaling Types +/// +/// @details +/// - Returns supported scaling capabilities +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pScalingCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedScalingCapability( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_caps_t* pScalingCaps ///< [in,out][release] Query result for supported scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Current Scaling +/// +/// @details +/// - Returns current active scaling +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pGetCurrentScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetCurrentScaling( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_settings_t* pGetCurrentScalingType ///< [in,out][release] Query result for active scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Scaling Type +/// +/// @details +/// - Returns current active scaling +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSetScalingType` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetCurrentScaling( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_scaling_settings_t* pSetScalingType ///< [in,out][release] Set scaling types + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Ambient light based enhancement table entry +typedef struct _ctl_lace_lux_aggr_map_entry_t +{ + uint32_t Lux; ///< [in,out] Ambient lux + uint8_t AggressivenessPercent; ///< [in,out] Pixel boost agressiveness + +} ctl_lace_lux_aggr_map_entry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Ambient light based enhancement table +typedef struct _ctl_lace_lux_aggr_map_t +{ + uint32_t MaxNumEntries; ///< [out] Max Number of entries in mapping table supported + uint32_t NumEntries; ///< [in,out] Number of entries in the given mapping table + ctl_lace_lux_aggr_map_entry_t* pLuxToAggrMappingTable; ///< [in] Max number of Entries which can be passed in + ///< LuxToAggrMappingTable + +} ctl_lace_lux_aggr_map_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Data specific to the mode caller is interested in +typedef union _ctl_lace_aggr_config_t +{ + uint8_t FixedAggressivenessLevelPercent; ///< [in,out] Fixed aggressiveness level, applicable for + ///< CTL_LACE_MODE_FIXED_AGGR_LEVEL + ctl_lace_lux_aggr_map_t AggrLevelMap; ///< [in,out] Lux to enhancement mapping table, applicable for + ///< CTL_LACE_MODE_AMBIENT_ADAPTIVE + +} ctl_lace_aggr_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Operations used for additional settings +typedef uint32_t ctl_get_operation_flags_t; +typedef enum _ctl_get_operation_flag_t +{ + CTL_GET_OPERATION_FLAG_CURRENT = CTL_BIT(0), ///< Get the details set through last set call + CTL_GET_OPERATION_FLAG_DEFAULT = CTL_BIT(1), ///< Get the driver default values + CTL_GET_OPERATION_FLAG_CAPABILITY = CTL_BIT(2), ///< Get capability + CTL_GET_OPERATION_FLAG_MAX = 0x80000000 + +} ctl_get_operation_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Operations used for additional settings +typedef enum _ctl_set_operation_t +{ + CTL_SET_OPERATION_RESTORE_DEFAULT = 0, ///< Restore default values + CTL_SET_OPERATION_CUSTOM = 1, ///< Set custom values + CTL_SET_OPERATION_MAX + +} ctl_set_operation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Lace Trigger Modes +typedef uint32_t ctl_lace_trigger_flags_t; +typedef enum _ctl_lace_trigger_flag_t +{ + CTL_LACE_TRIGGER_FLAG_AMBIENT_LIGHT = CTL_BIT(0), ///< LACE enhancement depends on Ambient light + CTL_LACE_TRIGGER_FLAG_FIXED_AGGRESSIVENESS = CTL_BIT(1),///< LACE enhancement is as per given fixed aggressiveness level + CTL_LACE_TRIGGER_FLAG_MAX = 0x80000000 + +} ctl_lace_trigger_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set/Get LACE Config +typedef struct _ctl_lace_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Enabled; ///< [in,out] Enable or disable LACE feature + ctl_get_operation_flags_t OpTypeGet; ///< [in] Get Operations used for additional settings + ctl_set_operation_t OpTypeSet; ///< [in] Set Operations used for additional settings + ctl_lace_trigger_flags_t Trigger; ///< [in,out] LACE operating mode to be Triggerd + ctl_lace_aggr_config_t LaceConfig; ///< [in,out] Data specific to the mode, caller is interested in + +} ctl_lace_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get LACE Config +/// +/// @details +/// - Returns current LACE Config +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLaceConfig` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED - "Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data passed by user" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetLACEConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_lace_config_t* pLaceConfig ///< [out]Lace configuration + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sets LACE Config +/// +/// @details +/// - Sets LACE Config +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLaceConfig` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_LACE_INVALID_DATA_ARGUMENT_PASSED - "Lace Incorrrect AggressivePercent data or LuxVsAggressive Map data passed by user" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetLACEConfig( + ctl_display_output_handle_t hDisplayOutput, ///< [in]Handle to display output + ctl_lace_config_t* pLaceConfig ///< [in]Lace configuration + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Software PSR status/Set Software PSR settings +typedef struct _ctl_sw_psr_settings_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Set; ///< [in][release] Set to False to Get Software PSR status. Set to True to + ///< Enable/Disable Software PSR + bool Supported; ///< [out] When Get is True, returns if SW PSR is supported + bool Enable; ///< [in,out] When Get is True, returns current state of Software PSR. + ///< When Get is False, Enables/Diasbles Software PSR + +} ctl_sw_psr_settings_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Software PSR caps/Set software PSR State +/// +/// @details +/// - Returns Software PSR status or Sets Software PSR capabilities. This is +/// a reserved capability. By default, software PSR is not supported/will +/// not be enabled, need application to activate it, please contact Intel +/// for activation. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSoftwarePsrSetting` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSoftwarePSR( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_sw_psr_settings_t* pSoftwarePsrSetting ///< [in,out][release] Get Software PSR caps/state or Set Software PSR + ///< state + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync Monitor Params +typedef struct _ctl_intel_arc_sync_monitor_params_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool IsIntelArcSyncSupported; ///< [out] Intel Arc Sync support for the monitor + float MinimumRefreshRateInHz; ///< [out] Minimum Intel Arc Sync refresh rate supported by the monitor + float MaximumRefreshRateInHz; ///< [out] Maximum Intel Arc Sync refresh rate supported by the monitor + uint32_t MaxFrameTimeIncreaseInUs; ///< [out] Max frame time increase in micro seconds from DID2.1 Adaptive + ///< Sync block + uint32_t MaxFrameTimeDecreaseInUs; ///< [out] Max frame time decrease in micro seconds from DID2.1 Adaptive + ///< Sync block + +} ctl_intel_arc_sync_monitor_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Intel Arc Sync information for monitor +/// +/// @details +/// - Returns Intel Arc Sync information for selected monitor +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncMonitorParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetIntelArcSyncInfoForMonitor( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_monitor_params_t* pIntelArcSyncMonitorParams ///< [in,out][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Handle of a MUX output instance +typedef struct _ctl_mux_output_handle_t *ctl_mux_output_handle_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enumerate Display MUX Devices on this system across adapters +/// +/// @details +/// - The application enumerates all MUX devices in the system +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hAPIHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +/// + `nullptr == phMuxDevices` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumerateMuxDevices( + ctl_api_handle_t hAPIHandle, ///< [in][release] Applications should pass the Control API handle returned + ///< by the CtlInit function + uint32_t* pCount, ///< [in,out][release] pointer to the number of MUX device instances. If + ///< input count is zero, then the api will update the value with the total + ///< number of MUX devices available and return the Count value. If input + ///< count is non-zero, then the api will only retrieve the number of MUX Devices. + ///< If count is larger than the number of MUX devices available, then the + ///< api will update the value with the correct number of MUX devices available. + ctl_mux_output_handle_t* phMuxDevices ///< [out][range(0, *pCount)] array of MUX device instance handles + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display MUX device properties +typedef struct _ctl_mux_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t MuxId; ///< [out] MUX ID of this MUX device enumerated + uint32_t Count; ///< [in,out] Pointer to the number of display output instances this MUX + ///< object can drive. If count is zero, then the api will update the value + ///< with the total + ///< number of outputs available. If count is non-zero, then the api will + ///< only retrieve the number of outputs. + ///< If count is larger than the number of display outputs MUX can drive, + ///< then the api will update the value with the correct number of display + ///< outputs MUX can driver. + ctl_display_output_handle_t* phDisplayOutputs; ///< [in,out][range(0, *pCount)] Array of display output instance handles + ///< this MUX device can drive + uint8_t IndexOfDisplayOutputOwningMux; ///< [out] [range(0, (Count-1))] This is the index into the + ///< phDisplayOutputs list to the display output which currently owns the + ///< MUX output. This doesn't mean display is active + +} ctl_mux_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Display Mux properties +/// +/// @details +/// - Get the propeties of the Mux device +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMuxDevice` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pMuxProperties` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetMuxProperties( + ctl_mux_output_handle_t hMuxDevice, ///< [in] MUX device instance handle + ctl_mux_properties_t* pMuxProperties ///< [in,out] MUX device properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Switch Mux output +/// +/// @details +/// - Switches the MUX output +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMuxDevice` +/// + `nullptr == hInactiveDisplayOutput` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSwitchMux( + ctl_mux_output_handle_t hMuxDevice, ///< [in] MUX device instance handle + ctl_display_output_handle_t hInactiveDisplayOutput ///< [out] Input selection for this MUX, which if active will drive the + ///< output of this MUX device. This should be one of the display output + ///< handles reported under this MUX device's properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync profile +typedef enum _ctl_intel_arc_sync_profile_t +{ + CTL_INTEL_ARC_SYNC_PROFILE_INVALID = 0, ///< Invalid profile + CTL_INTEL_ARC_SYNC_PROFILE_RECOMMENDED = 1, ///< Default. Selects appropriate profile based on the monitor. COMPATIBLE + ///< profile is applied if profile is not available for the monitor + CTL_INTEL_ARC_SYNC_PROFILE_EXCELLENT = 2, ///< Unconstrained. Full VRR range of the monitor can be used + CTL_INTEL_ARC_SYNC_PROFILE_GOOD = 3, ///< Some minor range constraints, unlikely to effect user experience but + ///< can reduce flicker on some monitors + CTL_INTEL_ARC_SYNC_PROFILE_COMPATIBLE = 4, ///< Significant constraints that will reduce flicker considerably but are + ///< likely to cause some level of judder onscreen especially when refresh + ///< rates are changing rapidly + CTL_INTEL_ARC_SYNC_PROFILE_OFF = 5, ///< Disable Intel Arc Sync on this monitor. This disables variable rate + ///< flips on this monitor. All sync flips will occur at the OS requested + ///< refresh rate + CTL_INTEL_ARC_SYNC_PROFILE_VESA = 6, ///< Applies vesa specified constraints if the monitor has provided them, + ///< COMPATIBLE profile if not + CTL_INTEL_ARC_SYNC_PROFILE_CUSTOM = 7, ///< Unlocks controls to set a custom Intel Arc Sync profile + CTL_INTEL_ARC_SYNC_PROFILE_MAX + +} ctl_intel_arc_sync_profile_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intel Arc Sync Profile Params +typedef struct _ctl_intel_arc_sync_profile_params_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_intel_arc_sync_profile_t IntelArcSyncProfile; ///< [in,out] Intel Arc Sync profile used by driver. Refer + ///< ::ctl_intel_arc_sync_profile_t + float MaxRefreshRateInHz; ///< [in,out] Maximum refresh rate utilized by the driver + float MinRefreshRateInHz; ///< [in,out] Minimum refresh rate utilized by the driver + uint32_t MaxFrameTimeIncreaseInUs; ///< [in,out] Maximum frame time increase (in micro seconds) imposed by the + ///< driver + uint32_t MaxFrameTimeDecreaseInUs; ///< [in,out] Maximum frame time decrease (in micro seconds) imposed by the + ///< driver + +} ctl_intel_arc_sync_profile_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Intel Arc Sync profile +/// +/// @details +/// - Returns Intel Arc Sync profile for selected monitor +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncProfileParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetIntelArcSyncProfile( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_profile_params_t* pIntelArcSyncProfileParams ///< [in,out][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set Intel Arc Sync profile +/// +/// @details +/// - Sets Intel Arc Sync profile for selected monitor. In a mux situation, +/// this API should be called for all display IDs associated with a +/// physical display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pIntelArcSyncProfileParams` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlSetIntelArcSyncProfile( + ctl_display_output_handle_t hDisplayOutput, ///< [in][release] Handle to display output + ctl_intel_arc_sync_profile_params_t* pIntelArcSyncProfileParams ///< [in][release] Intel Arc Sync params for monitor + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID Management operation type +typedef enum _ctl_edid_management_optype_t +{ + CTL_EDID_MANAGEMENT_OPTYPE_READ_EDID = 1, ///< This operation type is to read an output's EDID. Set edid_type input + ///< arg to read MONITOR EDID or previously OVERRIDDEN EDID or CURRENT + ///< active EDID. Read EDID is a 2 pass call. First call with size = 0, + ///< pEdidBuf = nullptr to get the size, then call with allocated buffer to + ///< get the EDID data. READ operation is applicable for any normal, edid + ///< locked or edid overridden display output device. + CTL_EDID_MANAGEMENT_OPTYPE_LOCK_EDID = 2, ///< To make an output always connected with OVERRIDE or MONITOR EDID + ///< across reboots. When output isn't connected call with OVERRIDE EDID; + ///< when connected, either set OVERRIDE and provide pEdidBuf or set + ///< MONITOR and driver will use monitor's EDID. There is no change to EDID + ///< stored in Monitor. Cannot be called when override is active. Any OS + ///< EDID override will take precedence over IGCL override. + CTL_EDID_MANAGEMENT_OPTYPE_UNLOCK_EDID = 3, ///< To undo lock EDID operation, i.e. it makes output as detached in + ///< response to unplug. This operation removes past supplied EDID; output + ///< status is reported to OS as it is; output restores back to monitor's + ///< EDID when it is connected + CTL_EDID_MANAGEMENT_OPTYPE_OVERRIDE_EDID = 4, ///< To replace an output's EDID with supplied one (pEdidBuf) only when + ///< physical display is connected. There is no change to EDID stored in + ///< Monitor. Cannot apply this operation on locked output. When no output + ///< device attached, the supplied EDID will be persisted in driver for + ///< future use. Any OS EDID override will take precedence over IGCL + ///< override. + CTL_EDID_MANAGEMENT_OPTYPE_UNDO_OVERRIDE_EDID = 5, ///< To undo override EDID operation, that is remove previously overridden + ///< EDID on an output. Output restores back to monitor's EDID when it is + ///< connected + CTL_EDID_MANAGEMENT_OPTYPE_MAX + +} ctl_edid_management_optype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID type. Used in LOCK_EDID and READ_EDID calls. +typedef enum _ctl_edid_type_t +{ + CTL_EDID_TYPE_CURRENT = 1, ///< [in] Used to return currently active EDID in READ_EDID call. + CTL_EDID_TYPE_OVERRIDE = 2, ///< [in] Is it user supplied EDID. Used in LOCK_EDID call with Supplied + ///< EDID or in READ_EDID to get Supplied EDID. + CTL_EDID_TYPE_MONITOR = 3, ///< [in] Is it Monitor's EDID. Used in LOCK_EDID and READ_EDID calls. + CTL_EDID_TYPE_MAX + +} ctl_edid_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Edid management operation Out Flags +typedef uint32_t ctl_edid_management_out_flags_t; +typedef enum _ctl_edid_management_out_flag_t +{ + CTL_EDID_MANAGEMENT_OUT_FLAG_OS_CONN_NOTIFICATION = CTL_BIT(0), ///< [out] If OS was notified about a connection change. App will need to + ///< wait for the OS action to complete. + CTL_EDID_MANAGEMENT_OUT_FLAG_SUPPLIED_EDID = CTL_BIT(1),///< [out] Is it previously supplied EDID, set for READ_EDID(CURRENT). + CTL_EDID_MANAGEMENT_OUT_FLAG_MONITOR_EDID = CTL_BIT(2), ///< [out] Is it Monitor's EDID, set for READ_EDID(CURRENT). + CTL_EDID_MANAGEMENT_OUT_FLAG_DISPLAY_CONNECTED = CTL_BIT(3),///< [out] Is Monitor physically connected + CTL_EDID_MANAGEMENT_OUT_FLAG_MAX = 0x80000000 + +} ctl_edid_management_out_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID management +typedef struct _ctl_edid_management_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_edid_management_optype_t OpType; ///< [in] EDID managmeent operation type + ctl_edid_type_t EdidType; ///< [in] EDID Type, Monitor or Supplied + uint32_t EdidSize; ///< [in,out] EDID Size, should be 0 for querying the size of EDID, should + ///< be previously returned size to read EDID. if buffer isn't big enough + ///< to fit EDID, returns size of EDID bytes. + uint8_t* pEdidBuf; ///< [in,out] buffer holding EDID data + ctl_edid_management_out_flags_t OutFlags; ///< [out] Output flags to inform about status of EDID management + ///< operations + +} ctl_edid_management_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief EDID Management allows managing an output's EDID or Plugged Status. +/// +/// @details +/// - To manage output's EDID or Display ID. Supports native DP SST and HDMI +/// Display types. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pEdidManagementArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters" +/// - ::CTL_RESULT_ERROR_DISPLAY_NOT_ATTACHED - "Error for Output Device not attached" +/// - ::CTL_RESULT_ERROR_OUT_OF_DEVICE_MEMORY - "Insufficient device memory to satisfy call" +/// - ::CTL_RESULT_ERROR_DATA_NOT_FOUND - "Requested EDID data not present." +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEdidManagement( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_edid_management_args_t* pEdidManagementArgs ///< [in,out] EDID management arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Custom mode operation types +typedef enum _ctl_custom_mode_operation_types_t +{ + CTL_CUSTOM_MODE_OPERATION_TYPES_GET_CUSTOM_SOURCE_MODES = 0,///< Get details of all previous applied custom modes if any. + CTL_CUSTOM_MODE_OPERATION_TYPES_ADD_CUSTOM_SOURCE_MODE = 1, ///< Add a new mode. Allows only single mode adition at a time. + CTL_CUSTOM_MODE_OPERATION_TYPES_REMOVE_CUSTOM_SOURCE_MODES = 2, ///< Remove previously added custom mode. Allows single or multiple mode + ///< removal at a time. + CTL_CUSTOM_MODE_OPERATION_TYPES_MAX + +} ctl_custom_mode_operation_types_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom Mode +typedef struct _ctl_get_set_custom_mode_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_custom_mode_operation_types_t CustomModeOpType; ///< [in] Custom mode operation type + uint32_t NumOfModes; ///< [in,out] Number of Custom Src Modes to be added/removed/Read. + ctl_custom_src_mode_t* pCustomSrcModeList; ///< [in,out] Custom mode source list which holds source modes to be + ///< added/removed/Read. + +} ctl_get_set_custom_mode_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom Mode +typedef struct _ctl_custom_src_mode_t +{ + uint32_t SourceX; ///< [in,out] CustomMode Source X Size + uint32_t SourceY; ///< [in,out] CustomMode Source Y Size + +} ctl_custom_src_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Custom mode. +/// +/// @details +/// - To get or set custom mode. +/// - Add custom source mode operation supports only single mode additon at +/// a time. +/// - Remove custom source mode operation supports single or multiple mode +/// removal at a time. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCustomModeArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernal mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_STANDARD_CUSTOM_MODE_EXISTS - "Standard custom mode exists" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_NON_CUSTOM_MATCHING_MODE_EXISTS - "Non custom matching mode exists" +/// - ::CTL_RESULT_ERROR_CUSTOM_MODE_INSUFFICIENT_MEMORY - "Custom mode insufficent memory" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetCustomMode( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_get_set_custom_mode_args_t* pCustomModeArgs ///< [in,out] Custom mode arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display operation type +typedef enum _ctl_combined_display_optype_t +{ + CTL_COMBINED_DISPLAY_OPTYPE_IS_SUPPORTED_CONFIG = 1,///< To check whether given outputs can form a combined display, no changes + ///< are applied + CTL_COMBINED_DISPLAY_OPTYPE_ENABLE = 2, ///< To setup and enable a combined display + CTL_COMBINED_DISPLAY_OPTYPE_DISABLE = 3, ///< To disable combined display + CTL_COMBINED_DISPLAY_OPTYPE_QUERY_CONFIG = 4, ///< To query combined display configuration + CTL_COMBINED_DISPLAY_OPTYPE_MAX + +} ctl_combined_display_optype_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display's child display target mode +typedef struct _ctl_child_display_target_mode_t +{ + uint32_t Width; ///< [in,out] Width + uint32_t Height; ///< [in,out] Height + float RefreshRate; ///< [in,out] Refresh Rate + uint32_t ReservedFields[4]; ///< [out] Reserved field of 16 bytes + +} ctl_child_display_target_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display's child display information +typedef struct _ctl_combined_display_child_info_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in,out] Display output handle under combined display configuration + ctl_rect_t FbSrc; ///< [in,out] FrameBuffer source's RECT within Combined Display respective + ctl_rect_t FbPos; ///< [in,out] FrameBuffer target's RECT within output size + ctl_display_orientation_t DisplayOrientation; ///< [in,out] 0/180 Degree Display orientation (rotation) + ctl_child_display_target_mode_t TargetMode; ///< [in,out] Desired target mode (width, height, refresh) + +} ctl_combined_display_child_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Combined Display arguments +typedef struct _ctl_combined_display_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_combined_display_optype_t OpType; ///< [in] Combined display operation type + bool IsSupported; ///< [out] Returns yes/no in response to IS_SUPPORTED_CONFIG command + uint8_t NumOutputs; ///< [in,out] Number of outputs part of desired combined display + ///< configuration + uint32_t CombinedDesktopWidth; ///< [in,out] Width of desired combined display configuration + uint32_t CombinedDesktopHeight; ///< [in,out] Height of desired combined display configuration + ctl_combined_display_child_info_t* pChildInfo; ///< [in,out] List of child display information respective to each output. + ///< Up to 16 displays are supported with up to 4 displays per GPU. + ctl_display_output_handle_t hCombinedDisplayOutput; ///< [in,out] Handle to combined display output + +} ctl_combined_display_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Combined Display +/// +/// @details +/// - To get or set combined display with given Child Targets on a Single +/// GPU or across identical GPUs. Multi-GPU(MGPU) combined display is +/// reserved i.e. it is not public and requires special application GUID. +/// MGPU Combined Display will get activated or deactivated in next boot. +/// MGPU scenario will internally link the associated adapters via Linked +/// Display Adapter Call, with supplied hDeviceAdapter being the LDA +/// Primary. If Genlock and enabled in Driver registry and supported by +/// given Display Config, MGPU Combined Display will enable MGPU Genlock +/// with supplied hDeviceAdapter being the Genlock Primary Adapter and the +/// First Child Display being the Primary Display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCombinedDisplayArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_FEATURE_NOT_SUPPORTED - "Combined Display feature is not supported in this platform" +/// - ::CTL_RESULT_ERROR_ADAPTER_NOT_SUPPORTED_ON_LDA_SECONDARY - "Unsupported (secondary) adapter handle passed" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetCombinedDisplay( + ctl_device_adapter_handle_t hDeviceAdapter, ///< [in][release] Handle to control device adapter + ctl_combined_display_args_t* pCombinedDisplayArgs ///< [in,out] Setup and get combined display arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Operations +typedef enum _ctl_genlock_operation_t +{ + CTL_GENLOCK_OPERATION_GET_TIMING_DETAILS = 0, ///< Get details of GENLOCK support and timing information + CTL_GENLOCK_OPERATION_VALIDATE = 1, ///< Driver to verify that the topology is Genlock capable + CTL_GENLOCK_OPERATION_ENABLE = 2, ///< Enable GENLOCK + CTL_GENLOCK_OPERATION_DISABLE = 3, ///< Disable GENLOCK + CTL_GENLOCK_OPERATION_GET_TOPOLOGY = 4, ///< Get details of the current Genlock topology that is applied + CTL_GENLOCK_OPERATION_MAX + +} ctl_genlock_operation_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Info +typedef struct _ctl_genlock_display_info_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in,out] Display output handle under Genlock topology + bool IsPrimary; ///< [in,out] Genlock Primary + +} ctl_genlock_display_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Genlock Target Mode List +typedef struct _ctl_genlock_target_mode_list_t +{ + ctl_display_output_handle_t hDisplayOutput; ///< [in] Display output handle for whom target mode list is required + uint32_t NumModes; ///< [in,out] Number of supported Modes that is returned from a driver + ctl_display_timing_t* pTargetModes; ///< [out] Display Genlock operation and information + +} ctl_genlock_target_mode_list_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Genlock Topology +typedef struct _ctl_genlock_topology_t +{ + uint8_t NumGenlockDisplays; ///< [in,out] Number of Genlock displays + bool IsPrimaryGenlockSystem; ///< [in,out] Primary Genlock system + ctl_display_timing_t CommonTargetMode; ///< [in] Common target mode + ctl_genlock_display_info_t* pGenlockDisplayInfo;///< [in,out] List of Genlock display info + ctl_genlock_target_mode_list_t* pGenlockModeList; ///< [out] List of Genlock target modes + +} ctl_genlock_topology_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Display Genlock Arg type +typedef struct _ctl_genlock_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_genlock_operation_t Operation; ///< [in] Display Genlock Operation + ctl_genlock_topology_t GenlockTopology; ///< [in,out] Display Genlock array of topology structures + bool IsGenlockEnabled; ///< [out] Whether the feature is currently enabled or not + bool IsGenlockPossible; ///< [out] Indicates if Genlock can be enabled/disabled with the given + ///< topology + +} ctl_genlock_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Display Genlock +/// +/// @details +/// - To get or set Display Genlock. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == hDeviceAdapter` +/// + `nullptr == pGenlockArgs` +/// + `nullptr == hFailureDeviceAdapter` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_INVALID_SIZE - "Invalid topology structure size" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetDisplayGenlock( + ctl_device_adapter_handle_t* hDeviceAdapter, ///< [in][release] Handle to control device adapter + ctl_genlock_args_t* pGenlockArgs, ///< [in,out] Display Genlock operation and information + uint32_t AdapterCount, ///< [in] Number of device adapters + ctl_device_adapter_handle_t* hFailureDeviceAdapter ///< [out] Handle to address the failure device adapter in an error case + ); + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_MAX_DISPLAYS_FOR_MGPU_COLLAGE +/// @brief Maximum number of displays for Single Large Screen +#define CTL_MAX_DISPLAYS_FOR_MGPU_COLLAGE 16 +#endif // CTL_MAX_DISPLAYS_FOR_MGPU_COLLAGE + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Vblank timestamp arguments +typedef struct _ctl_vblank_ts_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t NumOfTargets; ///< [out] Number of child targets + uint64_t VblankTS[CTL_MAX_DISPLAYS_FOR_MGPU_COLLAGE]; ///< [out] List of vblank timestamps in microseconds per child target + +} ctl_vblank_ts_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Vblank Timestamp +/// +/// @details +/// - To get a list of vblank timestamps in microseconds for each child +/// target of a display. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pVblankTSArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS - "Insufficient permissions" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetVblankTimestamp( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_vblank_ts_args_t* pVblankTSArgs ///< [out] Get vblank timestamp arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Link Display Adapters Arguments +typedef struct _ctl_lda_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint8_t NumAdapters; ///< [in,out] Numbers of adapters to be linked. Up to 4 adapters are + ///< supported + ctl_device_adapter_handle_t* hLinkedAdapters; ///< [in,out][release] List of Control device adapter handles to be linked, + ///< first one being Primary Adapter + uint64_t Reserved[4]; ///< [out] Reserved fields. Set to zero. + +} ctl_lda_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Link Display Adapters +/// +/// @details +/// - To Link Display Adapters. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPrimaryAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLdaArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_ADAPTER_ALREADY_LINKED - "Adapter is already linked" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlLinkDisplayAdapters( + ctl_device_adapter_handle_t hPrimaryAdapter, ///< [in][release] Handle to Primary adapter in LDA chain + ctl_lda_args_t* pLdaArgs ///< [in] Link Display Adapters Arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Unlink Display Adapters +/// +/// @details +/// - To Unlink Display Adapters +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPrimaryAdapter` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_ADAPTER_NOT_SUPPORTED_ON_LDA_SECONDARY - "Unsupported (secondary) adapter handle passed" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlUnlinkDisplayAdapters( + ctl_device_adapter_handle_t hPrimaryAdapter ///< [in][release] Handle to Primary adapter in LDA chain + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Linked Display Adapters +/// +/// @details +/// - To return list of Linked Display Adapters. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPrimaryAdapter` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLdaArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_ADAPTER_NOT_SUPPORTED_ON_LDA_SECONDARY - "Unsupported (secondary) adapter handle passed" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetLinkedDisplayAdapters( + ctl_device_adapter_handle_t hPrimaryAdapter, ///< [in][release] Handle to Primary adapter in LDA chain + ctl_lda_args_t* pLdaArgs ///< [out] Link Display Adapters Arguments + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Dynamic Contrast Enhancement arguments +typedef struct _ctl_dce_args_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool Set; ///< [in] Flag to indicate Set or Get operation + uint32_t TargetBrightnessPercent; ///< [in] Target brightness percent + double PhaseinSpeedMultiplier; ///< [in] Phase-in speed multiplier for brightness to take effect + uint32_t NumBins; ///< [in,out] Number of histogram bins + bool Enable; ///< [in,out] For get calls, this represents current state & for set this + ///< represents future state + bool IsSupported; ///< [out] is DCE feature supported + uint32_t* pHistogram; ///< [out] Bin wise histogram data of size NumBins * sizeof(uint32_t) for + ///< current frame + +} ctl_dce_args_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Dynamic Contrast Enhancement +/// +/// @details +/// - To get the DCE feature status and, if feature is enabled, returns the +/// current histogram, or to set the brightness at the phase-in speed +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDisplayOutput` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pDceArgs` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +/// - ::CTL_RESULT_ERROR_NULL_OS_DISPLAY_OUTPUT_HANDLE - "Null OS display output handle" +/// - ::CTL_RESULT_ERROR_NULL_OS_INTERFACE - "Null OS interface" +/// - ::CTL_RESULT_ERROR_NULL_OS_ADAPATER_HANDLE - "Null OS adapter handle" +/// - ::CTL_RESULT_ERROR_KMD_CALL - "Kernel mode driver call failure" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_HANDLE - "Invalid or Null handle passed" +/// - ::CTL_RESULT_ERROR_INVALID_NULL_POINTER - "Invalid null pointer" +/// - ::CTL_RESULT_ERROR_INVALID_OPERATION_TYPE - "Invalid operation type" +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT - "Invalid combination of parameters" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetDynamicContrastEnhancement( + ctl_display_output_handle_t hDisplayOutput, ///< [in] Handle to display output + ctl_dce_args_t* pDceArgs ///< [in,out] Dynamic Contrast Enhancement arguments + ); + + +#if !defined(__GNUC__) +#pragma endregion // display +#endif +// Intel 'ctlApi' for Device Adapter - Engine groups +#if !defined(__GNUC__) +#pragma region engine +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Accelerator engine groups +typedef enum _ctl_engine_group_t +{ + CTL_ENGINE_GROUP_GT = 0, ///< Access information about all engines combined. + CTL_ENGINE_GROUP_RENDER = 1, ///< Access information about all render and compute engines combined. + CTL_ENGINE_GROUP_MEDIA = 2, ///< Access information about all media engines combined. + CTL_ENGINE_GROUP_MAX + +} ctl_engine_group_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Engine group properties +typedef struct _ctl_engine_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_engine_group_t type; ///< [out] The engine group + +} ctl_engine_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Engine activity counters +/// +/// @details +/// - Percent utilization is calculated by taking two snapshots (s1, s2) and +/// using the equation: %util = (s2.activeTime - s1.activeTime) / +/// (s2.timestamp - s1.timestamp) +typedef struct _ctl_engine_stats_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t activeTime; ///< [out] Monotonic counter for time in microseconds that this resource is + ///< actively running workloads. + uint64_t timestamp; ///< [out] Monotonic timestamp counter in microseconds when activeTime + ///< counter was sampled. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_engine_stats_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of engine groups +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumEngineGroups( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_engine_handle_t* phEngine ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get engine group properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hEngine` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEngineGetProperties( + ctl_engine_handle_t hEngine, ///< [in] Handle for the component. + ctl_engine_properties_t* pProperties ///< [in,out] The properties for the specified engine group. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the activity stats for an engine group +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hEngine` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pStats` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEngineGetActivity( + ctl_engine_handle_t hEngine, ///< [in] Handle for the component. + ctl_engine_stats_t* pStats ///< [in,out] Will contain a snapshot of the engine group activity + ///< counters. + ); + + +#if !defined(__GNUC__) +#pragma endregion // engine +#endif +// Intel 'ctlApi' for Device Adapter- Fan management +#if !defined(__GNUC__) +#pragma region fan +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan resource speed mode +typedef enum _ctl_fan_speed_mode_t +{ + CTL_FAN_SPEED_MODE_DEFAULT = 0, ///< The fan speed is operating using the hardware default settings + CTL_FAN_SPEED_MODE_FIXED = 1, ///< The fan speed is currently set to a fixed value + CTL_FAN_SPEED_MODE_TABLE = 2, ///< The fan speed is currently controlled dynamically by hardware based on + ///< a temp/speed table + CTL_FAN_SPEED_MODE_MAX + +} ctl_fan_speed_mode_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed units +typedef enum _ctl_fan_speed_units_t +{ + CTL_FAN_SPEED_UNITS_RPM = 0, ///< The fan speed is in units of revolutions per minute (rpm) + CTL_FAN_SPEED_UNITS_PERCENT = 1, ///< The fan speed is a percentage of the maximum speed of the fan + CTL_FAN_SPEED_UNITS_MAX + +} ctl_fan_speed_units_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed +typedef struct _ctl_fan_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t speed; ///< [in,out] The speed of the fan. On output, a value of -1 indicates that + ///< there is no fixed fan speed setting. + ctl_fan_speed_units_t units; ///< [in,out] The units that the fan speed is expressed in. On output, if + ///< fan speed is -1 then units should be ignored. + +} ctl_fan_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan temperature/speed pair +typedef struct _ctl_fan_temp_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t temperature; ///< [in,out] Temperature in degrees Celsius. + ctl_fan_speed_t speed; ///< [in,out] The speed of the fan + +} ctl_fan_temp_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_FAN_TEMP_SPEED_PAIR_COUNT +/// @brief Maximum number of fan temperature/speed pairs in the fan speed table. +#define CTL_FAN_TEMP_SPEED_PAIR_COUNT 32 +#endif // CTL_FAN_TEMP_SPEED_PAIR_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan speed table +typedef struct _ctl_fan_speed_table_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t numPoints; ///< [in,out] The number of valid points in the fan speed table. 0 means + ///< that there is no fan speed table configured. -1 means that a fan speed + ///< table is not supported by the hardware. + ctl_fan_temp_speed_t table[CTL_FAN_TEMP_SPEED_PAIR_COUNT]; ///< [in,out] Array of temperature/fan speed pairs. The table is ordered + ///< based on temperature from lowest to highest. + +} ctl_fan_speed_table_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan properties +typedef struct _ctl_fan_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool canControl; ///< [out] Indicates if software can control the fan speed assuming the + ///< user has permissions + uint32_t supportedModes; ///< [out] Bitfield of supported fan configuration modes + ///< (1<<::ctl_fan_speed_mode_t) + uint32_t supportedUnits; ///< [out] Bitfield of supported fan speed units + ///< (1<<::ctl_fan_speed_units_t) + int32_t maxRPM; ///< [out] The maximum RPM of the fan. A value of -1 means that this + ///< property is unknown. + int32_t maxPoints; ///< [out] The maximum number of points in the fan temp/speed table. A + ///< value of -1 means that this fan doesn't support providing a temp/speed + ///< table. + +} ctl_fan_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Fan configuration +typedef struct _ctl_fan_config_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_fan_speed_mode_t mode; ///< [in,out] The fan speed mode (fixed, temp-speed table) + ctl_fan_speed_t speedFixed; ///< [in,out] The current fixed fan speed setting + ctl_fan_speed_table_t speedTable; ///< [out] A table containing temperature/speed pairs + +} ctl_fan_config_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of fans +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumFans( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to the adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_fan_handle_t* phFan ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get fan properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetProperties( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_properties_t* pProperties ///< [in,out] Will contain the properties of the fan. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get fan configurations and the current fan speed mode (default, fixed, +/// temp-speed table) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pConfig` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetConfig( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_config_t* pConfig ///< [in,out] Will contain the current configuration of the fan. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to run with hardware factory settings (set mode to +/// ::CTL_FAN_SPEED_MODE_DEFAULT) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetDefaultMode( + ctl_fan_handle_t hFan ///< [in] Handle for the component. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to rotate at a fixed speed (set mode to +/// ::CTL_FAN_SPEED_MODE_FIXED) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == speed` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + Fixing the fan speed not supported by the hardware or the fan speed units are not supported. See ::ctl_fan_properties_t.supportedModes and ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetFixedSpeedMode( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + const ctl_fan_speed_t* speed ///< [in] The fixed fan speed setting + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Configure the fan to adjust speed based on a temperature/speed table +/// (set mode to ::CTL_FAN_SPEED_MODE_TABLE) +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == speedTable` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_INVALID_ARGUMENT +/// + The temperature/speed pairs in the array are not sorted on temperature from lowest to highest. +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + Fan speed table not supported by the hardware or the fan speed units are not supported. See ::ctl_fan_properties_t.supportedModes and ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanSetSpeedTableMode( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + const ctl_fan_speed_table_t* speedTable ///< [in] A table containing temperature/speed pairs. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current state of a fan - current mode and speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFan` +/// - CTL_RESULT_ERROR_INVALID_ENUMERATION +/// + `::CTL_FAN_SPEED_UNITS_PERCENT < units` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSpeed` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_FEATURE +/// + The requested fan speed units are not supported. See ::ctl_fan_properties_t.supportedUnits. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFanGetState( + ctl_fan_handle_t hFan, ///< [in] Handle for the component. + ctl_fan_speed_units_t units, ///< [in] The units in which the fan speed should be returned. + int32_t* pSpeed ///< [in,out] Will contain the current speed of the fan in the units + ///< requested. A value of -1 indicates that the fan speed cannot be + ///< measured. + ); + + +#if !defined(__GNUC__) +#pragma endregion // fan +#endif +// Intel 'ctlApi' for Device Adapter - Frequency domains +#if !defined(__GNUC__) +#pragma region frequency +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency domains. +typedef enum _ctl_freq_domain_t +{ + CTL_FREQ_DOMAIN_GPU = 0, ///< GPU Core Domain. + CTL_FREQ_DOMAIN_MEMORY = 1, ///< Local Memory Domain. + CTL_FREQ_DOMAIN_MAX + +} ctl_freq_domain_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency properties +typedef struct _ctl_freq_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_freq_domain_t type; ///< [out] The hardware block that this frequency domain controls (GPU, + ///< memory, ...) + bool canControl; ///< [out] Indicates if software can control the frequency of this domain + ///< assuming the user has permissions + double min; ///< [out] The minimum hardware clock frequency in units of MHz. + double max; ///< [out] The maximum non-overclock hardware clock frequency in units of + ///< MHz. + +} ctl_freq_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency range between which the hardware can operate. The limits can +/// be above or below the hardware limits - the hardware will clamp +/// appropriately. +typedef struct _ctl_freq_range_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double min; ///< [in,out] The min frequency in MHz below which hardware frequency + ///< management will not request frequencies. On input, setting to 0 will + ///< permit the frequency to go down to the hardware minimum. On output, a + ///< negative value indicates that no external minimum frequency limit is + ///< in effect. + double max; ///< [in,out] The max frequency in MHz above which hardware frequency + ///< management will not request frequencies. On input, setting to 0 or a + ///< very big number will permit the frequency to go all the way up to the + ///< hardware maximum. On output, a negative number indicates that no + ///< external maximum frequency limit is in effect. + +} ctl_freq_range_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency throttle reasons +typedef uint32_t ctl_freq_throttle_reason_flags_t; +typedef enum _ctl_freq_throttle_reason_flag_t +{ + CTL_FREQ_THROTTLE_REASON_FLAG_AVE_PWR_CAP = CTL_BIT(0), ///< frequency throttled due to average power excursion (PL1) + CTL_FREQ_THROTTLE_REASON_FLAG_BURST_PWR_CAP = CTL_BIT(1), ///< frequency throttled due to burst power excursion (PL2) + CTL_FREQ_THROTTLE_REASON_FLAG_CURRENT_LIMIT = CTL_BIT(2), ///< frequency throttled due to current excursion (PL4) + CTL_FREQ_THROTTLE_REASON_FLAG_THERMAL_LIMIT = CTL_BIT(3), ///< frequency throttled due to thermal excursion (T > TjMax) + CTL_FREQ_THROTTLE_REASON_FLAG_PSU_ALERT = CTL_BIT(4), ///< frequency throttled due to power supply assertion + CTL_FREQ_THROTTLE_REASON_FLAG_SW_RANGE = CTL_BIT(5),///< frequency throttled due to software supplied frequency range + CTL_FREQ_THROTTLE_REASON_FLAG_HW_RANGE = CTL_BIT(6),///< frequency throttled due to a sub block that has a lower frequency + ///< range when it receives clocks + CTL_FREQ_THROTTLE_REASON_FLAG_MAX = 0x80000000 + +} ctl_freq_throttle_reason_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency state +typedef struct _ctl_freq_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double currentVoltage; ///< [out] Current voltage in Volts. A negative value indicates that this + ///< property is not known. + double request; ///< [out] The current frequency request in MHz. A negative value indicates + ///< that this property is not known. + double tdp; ///< [out] The maximum frequency in MHz supported under the current TDP + ///< conditions. This fluctuates dynamically based on the power and thermal + ///< limits of the part. A negative value indicates that this property is + ///< not known. + double efficient; ///< [out] The efficient minimum frequency in MHz. A negative value + ///< indicates that this property is not known. + double actual; ///< [out] The resolved frequency in MHz. A negative value indicates that + ///< this property is not known. + ctl_freq_throttle_reason_flags_t throttleReasons; ///< [out] The reasons that the frequency is being limited by the hardware. + ///< Returns 0 (frequency not throttled) or a combination of ::ctl_freq_throttle_reason_flag_t. + +} ctl_freq_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Frequency throttle time snapshot +/// +/// @details +/// - Percent time throttled is calculated by taking two snapshots (s1, s2) +/// and using the equation: %throttled = (s2.throttleTime - +/// s1.throttleTime) / (s2.timestamp - s1.timestamp) +typedef struct _ctl_freq_throttle_time_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t throttleTime; ///< [out] The monotonic counter of time in microseconds that the frequency + ///< has been limited by the hardware. + uint64_t timestamp; ///< [out] Microsecond timestamp when throttleTime was captured. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_freq_throttle_time_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of frequency domains +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumFrequencyDomains( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_freq_handle_t* phFrequency ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get frequency properties - available frequencies +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetProperties( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_properties_t* pProperties ///< [in,out] The frequency properties for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get available non-overclocked hardware clock frequencies for the +/// frequency domain +/// +/// @details +/// - The list of available frequencies is returned in order of slowest to +/// fastest. +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetAvailableClocks( + ctl_freq_handle_t hFrequency, ///< [in] Device handle of the device. + uint32_t* pCount, ///< [in,out] pointer to the number of frequencies. + ///< if count is zero, then the driver shall update the value with the + ///< total number of frequencies that are available. + ///< if count is greater than the number of frequencies that are available, + ///< then the driver shall update the value with the correct number of frequencies. + double* phFrequency ///< [in,out][optional][range(0, *pCount)] array of frequencies in units of + ///< MHz and sorted from slowest to fastest. + ///< if count is less than the number of frequencies that are available, + ///< then the driver shall only retrieve that number of frequencies. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current frequency limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLimits` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetRange( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_range_t* pLimits ///< [in,out] The range between which the hardware can operate for the + ///< specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set frequency range between which the hardware can operate. +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pLimits` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencySetRange( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + const ctl_freq_range_t* pLimits ///< [in] The limits between which the hardware can operate for the + ///< specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current frequency state - frequency request, actual frequency, TDP +/// limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetState( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_state_t* pState ///< [in,out] Frequency state for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get frequency throttle time +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hFrequency` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pThrottleTime` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlFrequencyGetThrottleTime( + ctl_freq_handle_t hFrequency, ///< [in] Handle for the component. + ctl_freq_throttle_time_t* pThrottleTime ///< [in,out] Will contain a snapshot of the throttle time counters for the + ///< specified domain. + ); + + +#if !defined(__GNUC__) +#pragma endregion // frequency +#endif +// Intel 'ctlApi' for Device Adapter +#if !defined(__GNUC__) +#pragma region media +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Feature type +typedef enum _ctl_video_processing_feature_t +{ + CTL_VIDEO_PROCESSING_FEATURE_FILM_MODE_DETECTION = 0, ///< Film mode detection. Contains CTL_PROPERTY_VALUE_TYPE_BOOL ValueType. + CTL_VIDEO_PROCESSING_FEATURE_NOISE_REDUCTION = 1, ///< Noise reduction. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field + ///< using struct ::ctl_video_processing_noise_reduction_t. + CTL_VIDEO_PROCESSING_FEATURE_SHARPNESS = 2, ///< Sharpness. Contains CTL_PROPERTY_VALUE_TYPE_UINT32 ValueType. + CTL_VIDEO_PROCESSING_FEATURE_ADAPTIVE_CONTRAST_ENHANCEMENT = 3, ///< Adaptive contrast enhancement. Contains + ///< CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using struct + ///< ::ctl_video_processing_adaptive_contrast_enhancement_t. + CTL_VIDEO_PROCESSING_FEATURE_SUPER_RESOLUTION = 4, ///< Super resolution. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM ValueType + ///< using ::ctl_video_processing_super_resolution_t. By defaut, Super + ///< resolution is not active, need application to activate it, please + ///< contact Intel for super resolution activation. + CTL_VIDEO_PROCESSING_FEATURE_STANDARD_COLOR_CORRECTION = 5, ///< Standard color correction. Controls Hue, Saturation, Contrast, + ///< Brightness. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using + ///< struct ::ctl_video_processing_standard_color_correction_t. + CTL_VIDEO_PROCESSING_FEATURE_TOTAL_COLOR_CORRECTION = 6,///< Total color correction. Controls Red, Green, Blue, Yellow, Cyan, + ///< Magenta. Contains CTL_PROPERTY_VALUE_TYPE_CUSTOM type field using + ///< struct ::ctl_video_processing_total_color_correction_t. + CTL_VIDEO_PROCESSING_FEATURE_SKIN_TONE_ENHANCEMENT = 7, ///< Skin tone enhancement. Contains CTL_PROPERTY_VALUE_TYPE_UINT32 + ///< ValueType. + CTL_VIDEO_PROCESSING_FEATURE_MAX + +} ctl_video_processing_feature_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super resolution values possible +typedef uint32_t ctl_video_processing_super_resolution_flags_t; +typedef enum _ctl_video_processing_super_resolution_flag_t +{ + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_DISABLE = CTL_BIT(0),///< Disable + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_DEFAULT_SCENARIO_MODE = CTL_BIT(1), ///< Enable with default super resolution mode + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_CONFERENCE_SCENARIO_MODE = CTL_BIT(2),///< Super resolution mode targeted at video conference content + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_ENABLE_CAMERA_SCENARIO_MODE = CTL_BIT(3),///< Super resolution mode targeted at camera capture content (e.g. + ///< security camera) + CTL_VIDEO_PROCESSING_SUPER_RESOLUTION_FLAG_MAX = 0x80000000 + +} ctl_video_processing_super_resolution_flag_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super Resolution feature details structure to be used with +/// SUPER_RESOLUTION +typedef struct _ctl_video_processing_super_resolution_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_super_resolution_flags_t super_resolution_flag;///< [in,out] SUPER_RESOLUTION flag + ctl_property_info_uint_t super_resolution_range_in_width; ///< [in,out] The range of input width information(min, max, default and + ///< step size)which super resolution is capable of supporting. + ctl_property_info_uint_t super_resolution_range_in_height; ///< [in,out] The range of input height information(min, max, default and + ///< step size)which super resolution is capable of supporting. + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_super_resolution_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Super Resolution Get/Set structure to be used with SUPER_RESOLUTION +typedef struct _ctl_video_processing_super_resolution_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_super_resolution_flags_t super_resolution_flag;///< [in,out] SUPER_RESOLUTION flag + bool super_resolution_max_in_enabled; ///< [in,out] The enabling of maximum input width and height limition. If + ///< enabled, super resolution will always take effect if the input + ///< resolution is smaller than the below specified max resolution; + ///< otherwise, super_resolution_max_in_width and + ///< super_resolution_max_in_height will be ignored + uint32_t super_resolution_max_in_width; ///< [in,out] The maximum input width limition value setting which super + ///< resolution will be allowed to enabled. + uint32_t super_resolution_max_in_height; ///< [in,out] The maximum input height limiation value setting which super + ///< resolution will be allowed to enabled. + bool super_resolution_reboot_reset; ///< [in,out] Resetting of super resolution after rebooting. + uint32_t ReservedFields[15]; ///< [out] Reserved field of 60 bytes + char ReservedBytes[3]; ///< [out] Reserved field of 3 bytes + +} ctl_video_processing_super_resolution_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Noise Reduction feature details structure to be used with +/// NOISE_REDUCTION +typedef struct _ctl_video_processing_noise_reduction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_info_uint_t noise_reduction; ///< [in,out] Noise reduction min, max, default and step size information + bool noise_reduction_auto_detect_supported; ///< [in,out] Noise reduction Auto Detect is supported; only valid if + ///< NOISE_REDUCTION is enabled. If enabled, noise reduction level is + ///< automatically determined and set value is not used. + ctl_property_info_boolean_t noise_reduction_auto_detect;///< [in,out] Noise reduction auto detect default information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_noise_reduction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Noise Reduction Get/Set structure to be used with NOISE_REDUCTION +typedef struct _ctl_video_processing_noise_reduction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_uint_t noise_reduction; ///< [in,out] Noise reduction enable and value setting + ctl_property_boolean_t noise_reduction_auto_detect; ///< [in,out] Noise reduction auto detect setting + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_noise_reduction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Contrast Enhancement feature details structure to be used +/// with ADAPTIVE_CONTRAST_ENHANCEMENT +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_info_uint_t adaptive_contrast_enhancement; ///< [in,out] Adaptive Contrast Enhancement min, max, default and step size + ///< information + bool adaptive_contrast_enhancement_coexistence_supported; ///< [in,out] Adaptive contrast enhancement coexistance is supported; only + ///< valid if ADAPTIVE_CONTRAST_ENHANCEMENT is enabled. If enabled, Video + ///< adaptive contrast ehancement will be allowed to be enabled and coexist + ///< with Display adaptive contrast ehancement feature. + ctl_property_info_boolean_t adaptive_contrast_enhancement_coexistence; ///< [in,out] Adaptive contrast enhancement coexistence default information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_adaptive_contrast_enhancement_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Adaptive Contrast Enhancement Get/Set structure to be used with +/// ADAPTIVE_CONTRAST_ENHANCEMENT +typedef struct _ctl_video_processing_adaptive_contrast_enhancement_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_property_uint_t adaptive_contrast_enhancement; ///< [in,out] Adaptive Contrast Enhancement enable and value setting + ctl_property_boolean_t adaptive_contrast_enhancement_coexistence; ///< [in,out] Adaptive contrast enhancement coexistance setting + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_adaptive_contrast_enhancement_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Standard Color Correction feature details structure to be used with +/// STANDARD_COLOR_CORRECTION +typedef struct _ctl_video_processing_standard_color_correction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool standard_color_correction_default_enable; ///< [in,out] STANDARD_COLOR_CORRECTION default enable setting. This + ///< global settings controls all of Hue, Saturation, Contrast, Brightness + ///< enabling. Individual Enable controls shall be ignored. + ctl_property_info_float_t brightness; ///< [in,out] Brightness min, max, default and step size information + ctl_property_info_float_t contrast; ///< [in,out] Contrast min, max, default and step size information + ctl_property_info_float_t hue; ///< [in,out] Hue min, max, default and step size information + ctl_property_info_float_t saturation; ///< [in,out] Saturation min, max, default and step size information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_standard_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Standard Color Correction Get/Set structure to be used with +/// STANDARD_COLOR_CORRECTION +typedef struct _ctl_video_processing_standard_color_correction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool standard_color_correction_enable; ///< [in,out] STANDARD_COLOR_CORRECTION enable setting. This global + ///< setting controls all of Hue, Saturation, Contrast, Brightness + ///< enabling. + float brightness; ///< [in,out] Brightness value + float contrast; ///< [in,out] Contrast value + float hue; ///< [in,out] Hue value + float saturation; ///< [in,out] Saturation value + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_standard_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Total Color Correction Get/Set structure to be used with +/// TOTAL_COLOR_CORRECTION +typedef struct _ctl_video_processing_total_color_correction_info_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool total_color_correction_default_enable; ///< [in,out] TOTAL_COLOR_CORRECTION enable setting. This global setting + ///< controls all of Red, Green, Blue, Yellow, Cyan, Magenta enabling. + ///< Individual Enable controls shall be ignored. + ctl_property_info_uint_t red; ///< [in,out] Red min, max, default and step size information + ctl_property_info_uint_t green; ///< [in,out] Green min, max, default and step size information + ctl_property_info_uint_t blue; ///< [in,out] Blue min, max, default and step size information + ctl_property_info_uint_t yellow; ///< [in,out] Yellow min, max, default and step size information + ctl_property_info_uint_t cyan; ///< [in,out] Cyan min, max, default and step size information + ctl_property_info_uint_t magenta; ///< [in,out] Magenta min, max, default and step size information + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_total_color_correction_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Total Color Correction Get/Set structure to be used with +/// TOTAL_COLOR_CORRECTION +typedef struct _ctl_video_processing_total_color_correction_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool total_color_correction_enable; ///< [in,out] TOTAL_COLOR_CORRECTION enable setting. This global setting + ///< controls all of Red, Green, Blue, Yellow, Cyan, Magenta enabling. + uint32_t red; ///< [in,out] Red value + uint32_t green; ///< [in,out] Green value + uint32_t blue; ///< [in,out] Blue value + uint32_t yellow; ///< [in,out] Yellow value + uint32_t cyan; ///< [in,out] Cyan value + uint32_t magenta; ///< [in,out] Magenta value + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_total_color_correction_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing feature details which will have range supported and +/// default values +typedef struct _ctl_video_processing_feature_details_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_feature_t FeatureType; ///< [out] Video processing feature type + ctl_property_value_type_t ValueType; ///< [out] Type of value + ctl_property_info_t Value; ///< [out] Union of various type of values for Video Processing features. + ///< For enum types this can be noise reduction, color control etc. This + ///< member is valid iff ValueType is not CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Features that use CustomType, + ///< after the first query for all of the supported features the user needs + ///< to allocate this buffer and then query again just this specific + ///< feature for the structure to be filled in. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM. + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_details_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing features which are controllable +typedef struct _ctl_video_processing_feature_caps_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t NumSupportedFeatures; ///< [in,out] Number of elements in supported features array + ctl_video_processing_feature_details_t* pFeatureDetails;///< [in,out] Array of supported features and their details + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_caps_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Video Processing feature for get/set +typedef struct _ctl_video_processing_feature_getset_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_video_processing_feature_t FeatureType; ///< [in] Features interested in + char* ApplicationName; ///< [in] Application name for which the property type is applicable. If + ///< this is an empty string then this will get/set global settings for the + ///< given adapter. Note that this should contain only the name of the + ///< application and not the system specific path. [This is not currently + ///< supported and should be an empty string.] + int8_t ApplicationNameLength; ///< [in] Length of ApplicationName string + bool bSet; ///< [in] Set this if it's a set call + ctl_property_value_type_t ValueType; ///< [in] Type of value. Caller has to ensure it provides the right value + ///< type which decides how one read the union structure below + ctl_property_t Value; ///< [in,out] Union of various type of values for Video Processing + ///< features. For enum types this can be noise reduction, color control + ///< etc. This member is valid iff ValueType is not + ///< CTL_PROPERTY_VALUE_TYPE_CUSTOM + int32_t CustomValueSize; ///< [in] CustomValue buffer size. For a feature requiring custom struct, + ///< caller will know of it upfront the struct to use based on the feautre + ///< and can provide the right size info here + void* pCustomValue; ///< [in,out] Pointer to a custom structure. Caller should allocate this + ///< buffer with known custom feature structure size. This member is valid + ///< iff ValueType is CTL_PROPERTY_VALUE_TYPE_CUSTOM + uint32_t ReservedFields[16]; ///< [out] Reserved field of 64 bytes + +} ctl_video_processing_feature_getset_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Video Processing capabilities +/// +/// @details +/// - The application gets Video Processing properties +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeatureCaps` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSupportedVideoProcessingCapabilities( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_video_processing_feature_caps_t* pFeatureCaps ///< [in,out][release] Video Processing properties + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get/Set Video Processing feature details +/// +/// @details +/// - Video Processing feature details +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pFeature` +/// - ::CTL_RESULT_ERROR_UNSUPPORTED_VERSION - "Unsupported version" +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlGetSetVideoProcessingFeature( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_video_processing_feature_getset_t* pFeature ///< [in][release] Video Processing feature get/set parameter + ); + + +#if !defined(__GNUC__) +#pragma endregion // media +#endif +// Intel 'ctlApi' for Device Adapter - Memory management +#if !defined(__GNUC__) +#pragma region memory +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory module types +typedef enum _ctl_mem_type_t +{ + CTL_MEM_TYPE_HBM = 0, ///< HBM memory + CTL_MEM_TYPE_DDR = 1, ///< DDR memory + CTL_MEM_TYPE_DDR3 = 2, ///< DDR3 memory + CTL_MEM_TYPE_DDR4 = 3, ///< DDR4 memory + CTL_MEM_TYPE_DDR5 = 4, ///< DDR5 memory + CTL_MEM_TYPE_LPDDR = 5, ///< LPDDR memory + CTL_MEM_TYPE_LPDDR3 = 6, ///< LPDDR3 memory + CTL_MEM_TYPE_LPDDR4 = 7, ///< LPDDR4 memory + CTL_MEM_TYPE_LPDDR5 = 8, ///< LPDDR5 memory + CTL_MEM_TYPE_GDDR4 = 9, ///< GDDR4 memory + CTL_MEM_TYPE_GDDR5 = 10, ///< GDDR5 memory + CTL_MEM_TYPE_GDDR5X = 11, ///< GDDR5X memory + CTL_MEM_TYPE_GDDR6 = 12, ///< GDDR6 memory + CTL_MEM_TYPE_GDDR6X = 13, ///< GDDR6X memory + CTL_MEM_TYPE_GDDR7 = 14, ///< GDDR7 memory + CTL_MEM_TYPE_UNKNOWN = 15, ///< UNKNOWN memory + CTL_MEM_TYPE_MAX + +} ctl_mem_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory module location +typedef enum _ctl_mem_loc_t +{ + CTL_MEM_LOC_SYSTEM = 0, ///< System memory + CTL_MEM_LOC_DEVICE = 1, ///< On board local device memory + CTL_MEM_LOC_MAX + +} ctl_mem_loc_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory properties +typedef struct _ctl_mem_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_mem_type_t type; ///< [out] The memory type + ctl_mem_loc_t location; ///< [out] Location of this memory (system, device) + uint64_t physicalSize; ///< [out] Physical memory size in bytes. A value of 0 indicates that this + ///< property is not known. However, a call to ::ctlMemoryGetState() will + ///< correctly return the total size of usable memory. + int32_t busWidth; ///< [out] Width of the memory bus. A value of -1 means that this property + ///< is unknown. + int32_t numChannels; ///< [out] The number of memory channels. A value of -1 means that this + ///< property is unknown. + +} ctl_mem_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory state - health, allocated +/// +/// @details +/// - Percent allocation is given by 100 * (size - free / size. +/// - Percent free is given by 100 * free / size. +typedef struct _ctl_mem_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t free; ///< [out] The free memory in bytes + uint64_t size; ///< [out] The total allocatable memory in bytes (can be less than + ///< ::ctl_mem_properties_t.physicalSize) + +} ctl_mem_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Memory bandwidth +/// +/// @details +/// - Percent bandwidth is calculated by taking two snapshots (s1, s2) and +/// using the equation: %bw = 10^6 * ((s2.readCounter - s1.readCounter) + +/// (s2.writeCounter - s1.writeCounter)) / (s2.maxBandwidth * +/// (s2.timestamp - s1.timestamp)) +typedef struct _ctl_mem_bandwidth_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t maxBandwidth; ///< [out] Current maximum bandwidth in units of bytes/sec + uint64_t timestamp; ///< [out] The timestamp (in microseconds) when these measurements were sampled. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + uint64_t readCounter; ///< [out] Total bytes read from memory. Supported only for Version > 0 + uint64_t writeCounter; ///< [out] Total bytes written to memory. Supported only for Version > 0 + +} ctl_mem_bandwidth_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of memory modules +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumMemoryModules( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_mem_handle_t* phMemory ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetProperties( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_properties_t* pProperties ///< [in,out] Will contain memory properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory state - health, allocated +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetState( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_state_t* pState ///< [in,out] Will contain the current health and allocated memory. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get memory bandwidth +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hMemory` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pBandwidth` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to query this telemetry. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlMemoryGetBandwidth( + ctl_mem_handle_t hMemory, ///< [in] Handle for the component. + ctl_mem_bandwidth_t* pBandwidth ///< [in,out] Will contain the current health, free memory, total memory + ///< size. + ); + + +#if !defined(__GNUC__) +#pragma endregion // memory +#endif +// Intel 'ctlApi' for Device Adapter - Overclock +#if !defined(__GNUC__) +#pragma region overclock +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Telemetry Item for each telemetry property +/// +/// @details +/// - If the supported field is true, then the entire structure has valid +/// information. +/// - The ::ctl_data_value_t is of type ::ctl_data_type_t and units +/// ::ctl_units_t +typedef struct _ctl_oc_telemetry_item_t +{ + bool bSupported; ///< [out] Indicates if the value is supported. + ctl_units_t units; ///< [out] Indicates the units of the value. + ctl_data_type_t type; ///< [out] Indicates the data type. + ctl_data_value_t value; ///< [out] The value of type ::ctl_data_type_t and units ::ctl_units_t. + +} ctl_oc_telemetry_item_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclocking Control Information +/// +/// @details +/// - Whether the device supports overclocking. +/// - The +/// bSupported/bRelative/bReference/units/min/max/step/default/reference +/// values for the available overclock controls +/// - The idea is to facilitate the way the applications present overclock +/// settings to the user. If bSupported is false, the corresponding +/// overclock control is not supported +/// - The setting units will be an enum that enables the application to know +/// the units for the control setting e.g. MHz. The min and max settings +/// give the limits for the control. +/// - The step setting gives the minimum change in the control value (plus +/// or minus) - if a control is not changed by at least this amount, the +/// hardware may round up or down. +/// - The default values gives the manufacturing setting for the control. +/// Some controls such as frequency offset and voltage offset are +/// relative; in this case, bRelative will be true, otherwise the control +/// settings are absolute values. +/// - For relative controls and if bReference is true, the reference value +/// gives the absolute value at the default setting. +/// - If bReference is false, the absolute value of the default setting is +/// no not known and it is probably better to display the setting to users +/// as percentage offsets. +typedef struct _ctl_oc_control_info_t +{ + bool bSupported; ///< [out] Indicates if the values are known. + bool bRelative; ///< [out] Indicates if the values are meant to be taken as relative values + ///< instead of absolut values. + bool bReference; ///< [out] For relative values, this indicates if a reference is available. + ctl_units_t units; ///< [out] Units for the values. + double min; ///< [out] Minimum Value. + double max; ///< [out] Maximum Value. + double step; ///< [out] Step Value. + double Default; ///< [out] Default Value. + double reference; ///< [out] Reference Value if the bReference is true. + +} ctl_oc_control_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock properties +typedef struct _ctl_oc_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool bSupported; ///< [out] Indicates if the adapter supports overclocking. + ctl_oc_control_info_t gpuFrequencyOffset; ///< [out] related to function ::ctlOverclockGpuFrequencyOffsetSet + ctl_oc_control_info_t gpuVoltageOffset; ///< [out] related to function ::ctlOverclockGpuVoltageOffsetSet + ctl_oc_control_info_t vramFrequencyOffset; ///< [out] Property Field Deprecated / No Longer Supported + ctl_oc_control_info_t vramVoltageOffset; ///< [out] Property Field Deprecated / No Longer Supported + ctl_oc_control_info_t powerLimit; ///< [out] related to function ::ctlOverclockPowerLimitSet + ctl_oc_control_info_t temperatureLimit; ///< [out] related to function ::ctlOverclockTemperatureLimitSet + +} ctl_oc_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock Voltage Frequency Pair +typedef struct _ctl_oc_vf_pair_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + double Voltage; ///< [in,out] Voltage component of the pair in mV. + double Frequency; ///< [in,out] Frequency component of the pair in MHz. + +} ctl_oc_vf_pair_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_PSU_COUNT +/// @brief Maximum number power supply units. +#define CTL_PSU_COUNT 5 +#endif // CTL_PSU_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSU Type. +typedef enum _ctl_psu_type_t +{ + CTL_PSU_TYPE_PSU_NONE = 0, ///< Type of the PSU is unknown. + CTL_PSU_TYPE_PSU_PCIE = 1, ///< Type of the PSU is PCIe + CTL_PSU_TYPE_PSU_6PIN = 2, ///< Type of the PSU is 6 PIN + CTL_PSU_TYPE_PSU_8PIN = 3, ///< Type of the PSU is 8 PIN + CTL_PSU_TYPE_MAX + +} ctl_psu_type_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PSU Info +typedef struct _ctl_psu_info_t +{ + bool bSupported; ///< [out] Indicates if this PSU entry is supported. + ctl_psu_type_t psuType; ///< [out] Type of the PSU. + ctl_oc_telemetry_item_t energyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed this power source. By taking the + ///< delta between two snapshots and dividing by the delta time in seconds, + ///< an application can compute the average power. + ctl_oc_telemetry_item_t voltage; ///< [out] Instantaneous snapshot of the voltage of this power source. + +} ctl_psu_info_t; + +/////////////////////////////////////////////////////////////////////////////// +#ifndef CTL_FAN_COUNT +/// @brief Maximum number of Fans +#define CTL_FAN_COUNT 5 +#endif // CTL_FAN_COUNT + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power Telemetry +typedef struct _ctl_power_telemetry_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_oc_telemetry_item_t timeStamp; ///< [out] Snapshot of the timestamp counter that measures the total time + ///< since Jan 1, 1970 UTC. It is a decimal value in seconds with a minimum + ///< accuracy of 1 millisecond. + ctl_oc_telemetry_item_t gpuEnergyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed by the GPU chip. By taking the + ///< delta between two snapshots and dividing by the delta time in seconds, + ///< an application can compute the average power. + ctl_oc_telemetry_item_t gpuVoltage; ///< [out] Instantaneous snapshot of the voltage feeding the GPU chip. It + ///< is measured at the power supply output - chip input will be lower. + ctl_oc_telemetry_item_t gpuCurrentClockFrequency; ///< [out] Instantaneous snapshot of the GPU chip frequency. + ctl_oc_telemetry_item_t gpuCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from + ///< the sensor reporting the highest value. + ctl_oc_telemetry_item_t globalActivityCounter; ///< [out] Snapshot of the monotonic global activity counter. It measures + ///< the time in seconds (accurate down to 1 millisecond) that any GPU + ///< engine is busy. By taking the delta between two snapshots and dividing + ///< by the delta time in seconds, an application can compute the average + ///< percentage utilization of the GPU.. + ctl_oc_telemetry_item_t renderComputeActivityCounter; ///< [out] Snapshot of the monotonic 3D/compute activity counter. It + ///< measures the time in seconds (accurate down to 1 millisecond) that any + ///< 3D render/compute engine is busy. By taking the delta between two + ///< snapshots and dividing by the delta time in seconds, an application + ///< can compute the average percentage utilization of all 3D + ///< render/compute blocks in the GPU. + ctl_oc_telemetry_item_t mediaActivityCounter; ///< [out] Snapshot of the monotonic media activity counter. It measures + ///< the time in seconds (accurate down to 1 millisecond) that any media + ///< engine is busy. By taking the delta between two snapshots and dividing + ///< by the delta time in seconds, an application can compute the average + ///< percentage utilization of all media blocks in the GPU. + bool gpuPowerLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip is exceeding the maximum power limits. + ///< Increasing the power limits using ::ctlOverclockPowerLimitSet() is one + ///< way to remove this limitation. + bool gpuTemperatureLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip is exceeding the temperature limits. + ///< Increasing the temperature limits using + ///< ::ctlOverclockTemperatureLimitSet() is one way to reduce this + ///< limitation. Improving the cooling solution is another way. + bool gpuCurrentLimited; ///< [out] Instantaneous indication that the desired GPU frequency is being + ///< throttled because the GPU chip has exceeded the power supply current + ///< limits. A better power supply is required to reduce this limitation. + bool gpuVoltageLimited; ///< [out] Instantaneous indication that the GPU frequency cannot be + ///< increased because the voltage limits have been reached. Increase the + ///< voltage offset using ::ctlOverclockGpuVoltageOffsetSet() is one way to + ///< reduce this limitation. + bool gpuUtilizationLimited; ///< [out] Instantaneous indication that due to lower GPU utilization, the + ///< hardware has lowered the GPU frequency. + ctl_oc_telemetry_item_t vramEnergyCounter; ///< [out] Snapshot of the monotonic energy counter maintained by hardware. + ///< It measures the total energy consumed by the local memory modules. By + ///< taking the delta between two snapshots and dividing by the delta time + ///< in seconds, an application can compute the average power. + ctl_oc_telemetry_item_t vramVoltage; ///< [out] Instantaneous snapshot of the voltage feeding the memory + ///< modules. + ctl_oc_telemetry_item_t vramCurrentClockFrequency; ///< [out] Instantaneous snapshot of the raw clock frequency driving the + ///< memory modules. + ctl_oc_telemetry_item_t vramCurrentEffectiveFrequency; ///< [out] Instantaneous snapshot of the effective data transfer rate that + ///< the memory modules can sustain based on the current clock frequency.. + ctl_oc_telemetry_item_t vramReadBandwidthCounter; ///< [out] Instantaneous snapshot of the monotonic counter that measures + ///< the read traffic from the memory modules. By taking the delta between + ///< two snapshots and dividing by the delta time in seconds, an + ///< application can compute the average read bandwidth. + ctl_oc_telemetry_item_t vramWriteBandwidthCounter; ///< [out] Instantaneous snapshot of the monotonic counter that measures + ///< the write traffic to the memory modules. By taking the delta between + ///< two snapshots and dividing by the delta time in seconds, an + ///< application can compute the average write bandwidth. + ctl_oc_telemetry_item_t vramCurrentTemperature; ///< [out] Instantaneous snapshot of the GPU chip temperature, read from + ///< the sensor reporting the highest value. + bool vramPowerLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules are exceeding the maximum power + ///< limits. + bool vramTemperatureLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules are exceeding the temperature + ///< limits. + bool vramCurrentLimited; ///< [out] Instantaneous indication that the memory frequency is being + ///< throttled because the memory modules have exceeded the power supply + ///< current limits. + bool vramVoltageLimited; ///< [out] Instantaneous indication that the memory frequency cannot be + ///< increased because the voltage limits have been reached. + bool vramUtilizationLimited; ///< [out] Instantaneous indication that due to lower memory traffic, the + ///< hardware has lowered the memory frequency. + ctl_oc_telemetry_item_t totalCardEnergyCounter; ///< [out] Total Card Energy Counter. + ctl_psu_info_t psu[CTL_PSU_COUNT]; ///< [out] PSU voltage and power. + ctl_oc_telemetry_item_t fanSpeed[CTL_FAN_COUNT];///< [out] Fan speed. + +} ctl_power_telemetry_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get overclock properties - available properties. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGetProperties( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_properties_t* pOcProperties ///< [in,out] The overclocking properties for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Overclock Waiver - Warranty Waiver. +/// +/// @details +/// - Most of the overclock functions will return an error if the waiver is +/// not set. This is because most overclock settings will increase the +/// electric/thermal stress on the part and thus reduce its lifetime. +/// - By setting the waiver, the user is indicate that they are accepting a +/// reduction in the lifetime of the part. +/// - It is the responsibility of overclock applications to notify each user +/// at least once with a popup of the dangers and requiring acceptance. +/// - Only once the user has accepted should this function be called by the +/// application. +/// - It is acceptable for the application to cache the user choice and call +/// this function on future executions without issuing the popup. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockWaiverSet( + ctl_device_adapter_handle_t hDeviceHandle ///< [in][release] Handle to display adapter + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Frequency Offset for the GPU in MHz. +/// +/// @details +/// - Determine the current frequency offset in effect (refer to +/// ::ctlOverclockGpuFrequencyOffsetSet() for details). +/// - The value returned may be different from the value that was previously +/// set by the application depending on hardware limitations or if the +/// function ::ctlOverclockGpuFrequencyOffsetSet() has been called or +/// another application that has changed the value. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcFrequencyOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuFrequencyOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcFrequencyOffset ///< [in,out] The Turbo Overclocking Frequency Desired in MHz. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Frequency Offset for the GPU in MHZ. +/// +/// @details +/// - The purpose of this function is to increase/decrease the frequency at +/// which typical workloads will run within the same thermal budget. +/// - The frequency offset is expressed in units of ±1MHz. +/// - The actual operating frequency for each workload is not guaranteed to +/// change exactly by the specified offset. +/// - For positive frequency offsets, the factory maximum frequency may +/// increase by up to the specified amount. +/// - For negative frequency offsets, the overclock waiver must have been +/// set since this can result in running the part at voltages beyond the +/// part warrantee limits. An error is returned if the waiver has not been +/// set. +/// - Specifying large values for the frequency offset can lead to +/// instability. It is recommended that changes are made in small +/// increments and stability/performance measured running intense GPU +/// workloads before increasing further. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuFrequencyOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocFrequencyOffset ///< [in] The Turbo Overclocking Frequency Desired in MHz. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Gpu Voltage Offset in mV. +/// +/// @details +/// - Determine the current voltage offset in effect on the hardware (refer +/// to ::ctlOverclockGpuVoltageOffsetSet for details). +/// - The value returned may be different from the value that was previously +/// set by the application depending on hardware limitations or if the +/// function ::ctlOverclockGpuVoltageOffsetSet has been called or another +/// application that has changed the value. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcVoltageOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuVoltageOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcVoltageOffset ///< [in,out] The Turbo Overclocking Frequency Desired in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Gpu Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to attempt to run the GPU up to higher +/// voltages beyond the part warrantee limits. This can permit running at +/// even higher frequencies than can be obtained using the frequency +/// offset setting, but at the risk of reducing the lifetime of the part. +/// - The voltage offset is expressed in units of ±millivolts with values +/// permitted down to a resolution of 1 millivolt. +/// - The overclock waiver must be set before calling this function +/// otherwise and error will be returned. +/// - There is no guarantee that a workload can operate at the higher +/// frequencies permitted by this setting. Significantly more heat will be +/// generated at these high frequencies/voltages which will necessitate a +/// good cooling solution. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuVoltageOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocVoltageOffset ///< [in] The Turbo Overclocking Frequency Desired in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Gets the Locked GPU Voltage for Overclocking in mV. +/// +/// @details +/// - The purpose of this function is to determine if the current values of +/// the frequency/voltage lock. +/// - If the lock is not currently active, will return 0 for frequency and +/// voltage. +/// - Note that the operating frequency/voltage may be lower than these +/// settings if power/thermal limits are exceeded. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pVfPair` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuLockGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_vf_pair_t* pVfPair ///< [out] The current locked voltage and frequency. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Locks the GPU voltage for Overclocking in mV. +/// +/// @details +/// - The purpose of this function is to provide an interface for scanners +/// to lock the frequency and voltage to fixed values. +/// - The frequency is expressed in units of MHz with a resolution of 1MHz. +/// - The voltage is expressed in units of ±millivolts with values +/// permitted down to a resolution of 1 millivolt. +/// - The overclock waiver must be set since fixing the voltage at a high +/// value puts unnecessary stress on the part. +/// - The actual frequency may reduce depending on power/thermal +/// limitations. +/// - Requesting a frequency and/or voltage of 0 will return the hardware to +/// dynamic frequency/voltage management with any previous frequency +/// offset or voltage offset settings reapplied. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockGpuLockSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_oc_vf_pair_t vFPair ///< [in] The current locked voltage and frequency. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the current Vram Frequency Offset in GT/s. +/// +/// @details +/// - The purpose of this function is to return the current VRAM frequency +/// offset in units of GT/s. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pOcFrequencyOffset` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramFrequencyOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pOcFrequencyOffset ///< [in,out] The current Memory Frequency in GT/s. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the desired Vram frquency Offset in GT/s +/// +/// @details +/// - The purpose of this function is to increase/decrease the frequency of +/// VRAM. +/// - The frequency offset is expressed in units of GT/s with a minimum step +/// size given by ::ctlOverclockGetProperties. +/// - The actual operating frequency for each workload is not guaranteed to +/// change exactly by the specified offset. +/// - The waiver must be set using clibOverclockWaiverSet() before this +/// function can be called. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// - If the memory controller doesn't support changes to frequency on the +/// fly, one of the following return codes will be given: +/// - ::CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED: The requested memory +/// overclock will be applied when the device is reset or the system is +/// rebooted. In this case, the overclock software should check if the +/// overclock request was applied after the reset/reboot. If it was and +/// when the overclock application shuts down gracefully and if the +/// overclock application wants the setting to be persistent, the +/// application should request the same overclock settings again so that +/// they will be applied on the next reset/reboot. If this is not done, +/// then every time the device is reset and overclock is requested, the +/// device needs to be reset a second time. +/// - ::CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED: The requested memory +/// overclock will be applied when the system is rebooted. In this case, +/// the overclock software should check if the overclock request was +/// applied after the reboot. If it was and when the overclock application +/// shuts down gracefully and if the overclock application wants the +/// setting to be persistent, the application should request the same +/// overclock settings again so that they will be applied on the next +/// reset/reboot. If this is not done and the overclock setting is +/// requested after the reboot has occurred, a second reboot will be +/// required. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramFrequencyOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double ocFrequencyOffset ///< [in] The desired Memory Frequency in GT/s. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the Overclock Vram Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to increase/decrease the voltage of +/// VRAM. +/// - The voltage offset is expressed in units of millivolts with a minimum +/// step size given by ::ctlOverclockGetProperties. +/// - The waiver must be set using ::ctlOverclockWaiverSet before this +/// function can be called. +/// - This setting is not persistent through system reboots or driver +/// resets/hangs. It is up to the overclock application to reapply the +/// settings in those cases. +/// - This setting can cause system/device instability. It is up to the +/// overclock application to detect if the system has rebooted +/// unexpectedly or the device was restarted. When this occurs, the +/// application should not reapply the overclock settings automatically +/// but instead return to previously known good settings or notify the +/// user that the settings are not being applied. +/// - If the memory controller doesn't support changes to voltage on the +/// fly, one of the following return codes will be given: +/// - ::CTL_RESULT_ERROR_RESET_DEVICE_REQUIRED: The requested memory +/// overclock will be applied when the device is reset or the system is +/// rebooted. In this case, the overclock software should check if the +/// overclock request was applied after the reset/reboot. If it was and +/// when the overclock application shuts down gracefully and if the +/// overclock application wants the setting to be persistent, the +/// application should request the same overclock settings again so that +/// they will be applied on the next reset/reboot. If this is not done, +/// then every time the device is reset and overclock is requested, the +/// device needs to be reset a second time. +/// - ::CTL_RESULT_ERROR_FULL_REBOOT_REQUIRED: The requested memory +/// overclock will be applied when the system is rebooted. In this case, +/// the overclock software should check if the overclock request was +/// applied after the reboot. If it was and when the overclock application +/// shuts down gracefully and if the overclock application wants the +/// setting to be persistent, the application should request the same +/// overclock settings again so that they will be applied on the next +/// reset/reboot. If this is not done and the overclock setting is +/// requested after the reboot has occurred, a second reboot will be +/// required. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pVoltage` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramVoltageOffsetGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pVoltage ///< [out] The current locked voltage in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the Overclock Vram Voltage Offset in mV. +/// +/// @details +/// - The purpose of this function is to set the maximum sustained power +/// limit. If the average GPU power averaged over a few seconds exceeds +/// this value, the frequency of the GPU will be throttled. +/// - Set a value of 0 to disable this power limit. In this case, the GPU +/// frequency will not throttle due to average power but may hit other +/// limits. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockVramVoltageOffsetSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double voltage ///< [in] The voltage to be locked in mV. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the sustained power limit in mW. +/// +/// @details +/// - The purpose of this function is to read the current sustained power +/// limit. +/// - A value of 0 means that the limit is disabled - the GPU frequency can +/// run as high as possible until other limits are hit. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pSustainedPowerLimit` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockPowerLimitGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pSustainedPowerLimit ///< [in,out] The current sustained power limit in mW. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the sustained power limit in mW. +/// +/// @details +/// - The purpose of this function is to set the maximum sustained power +/// limit. If the average GPU power averaged over a few seconds exceeds +/// this value, the frequency of the GPU will be throttled. +/// - Set a value of 0 to disable this power limit. In this case, the GPU +/// frequency will not throttle due to average power but may hit other +/// limits. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockPowerLimitSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double sustainedPowerLimit ///< [in] The desired sustained power limit in mW. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the current temperature limit in Celsius. +/// +/// @details +/// - The purpose of this function is to read the current thermal limit. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTemperatureLimit` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockTemperatureLimitGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double* pTemperatureLimit ///< [in,out] The current temperature limit in Celsius. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set the temperature limit in Celsius. +/// +/// @details +/// - The purpose of this function is to change the maximum thermal limit. +/// When the GPU temperature exceeds this value, the GPU frequency will be +/// throttled. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockTemperatureLimitSet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + double temperatureLimit ///< [in] The desired temperature limit in Celsius. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get Power Telemetry. +/// +/// @details +/// - Limited rate of 50 ms, any call under 50 ms will return the same +/// information. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTelemetryInfo` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerTelemetryGet( + ctl_device_adapter_handle_t hDeviceHandle, ///< [in][release] Handle to display adapter + ctl_power_telemetry_t* pTelemetryInfo ///< [out] The overclocking properties for the specified domain. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Reset all Overclock Settings to stock +/// +/// @details +/// - Reset all Overclock setting to default using single API call +/// - This request resets any changes made to GpuFrequencyOffset, +/// GpuVoltageOffset, PowerLimit, TemperatureLimit, GpuLock +/// - This Doesn't reset any Fan Curve Changes. It can be reset using +/// ctlFanSetDefaultMode +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDeviceHandle` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlOverclockResetToDefault( + ctl_device_adapter_handle_t hDeviceHandle ///< [in][release] Handle to display adapter + ); + + +#if !defined(__GNUC__) +#pragma endregion // overclock +#endif +// Intel 'ctlApi' for Device Adapter - PCI Information +#if !defined(__GNUC__) +#pragma region pci +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief PCI address +typedef struct _ctl_pci_address_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint32_t domain; ///< [out] BDF domain + uint32_t bus; ///< [out] BDF bus + uint32_t device; ///< [out] BDF device + uint32_t function; ///< [out] BDF function + +} ctl_pci_address_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief PCI speed +typedef struct _ctl_pci_speed_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + int32_t gen; ///< [out] The link generation. A value of -1 means that this property is + ///< unknown. + int32_t width; ///< [out] The number of lanes. A value of -1 means that this property is + ///< unknown. + int64_t maxBandwidth; ///< [out] The maximum bandwidth in bytes/sec (sum of all lanes). A value + ///< of -1 means that this property is unknown. + +} ctl_pci_speed_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Static PCI properties +typedef struct _ctl_pci_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pci_address_t address; ///< [out] The BDF address + ctl_pci_speed_t maxSpeed; ///< [out] Fastest port configuration supported by the device (sum of all + ///< lanes) + bool resizable_bar_supported; ///< [out] Support for Resizable Bar on this device. + bool resizable_bar_enabled; ///< [out] Resizable Bar enabled on this device + +} ctl_pci_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Dynamic PCI state +typedef struct _ctl_pci_state_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_pci_speed_t speed; ///< [out] The current port configure speed + +} ctl_pci_state_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get PCI properties - address, max speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPciGetProperties( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_pci_properties_t* pProperties ///< [in,out] Will contain the PCI properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get current PCI state - current speed +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pState` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPciGetState( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + ctl_pci_state_t* pState ///< [in,out] Will contain the PCI properties. + ); + + +#if !defined(__GNUC__) +#pragma endregion // pci +#endif +// Intel 'ctlApi' for Device Adapter - Power management +#if !defined(__GNUC__) +#pragma region power +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Properties related to device power settings +typedef struct _ctl_power_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool canControl; ///< [out] Software can change the power limits of this domain assuming the + ///< user has permissions. + int32_t defaultLimit; ///< [out] The factory default TDP power limit of the part in milliwatts. A + ///< value of -1 means that this is not known. + int32_t minLimit; ///< [out] The minimum power limit in milliwatts that can be requested. + int32_t maxLimit; ///< [out] The maximum power limit in milliwatts that can be requested. + +} ctl_power_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Energy counter snapshot +/// +/// @details +/// - Average power is calculated by taking two snapshots (s1, s2) and using +/// the equation: PowerWatts = (s2.energy - s1.energy) / (s2.timestamp - +/// s1.timestamp) +typedef struct _ctl_power_energy_counter_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + uint64_t energy; ///< [out] The monotonic energy counter in microjoules. + uint64_t timestamp; ///< [out] Microsecond timestamp when energy was captured. + ///< This timestamp should only be used to calculate delta time between + ///< snapshots of this structure. + ///< Never take the delta of this timestamp with the timestamp from a + ///< different structure since they are not guaranteed to have the same base. + ///< The absolute value of the timestamp is only valid during within the + ///< application and may be different on the next execution. + +} ctl_power_energy_counter_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Sustained power limits +/// +/// @details +/// - The power controller (Punit) will throttle the operating frequency if +/// the power averaged over a window (typically seconds) exceeds this +/// limit. +typedef struct _ctl_power_sustained_limit_t +{ + bool enabled; ///< [in,out] indicates if the limit is enabled (true) or ignored (false) + int32_t power; ///< [in,out] power limit in milliwatts + int32_t interval; ///< [in,out] power averaging window (Tau) in milliseconds + +} ctl_power_sustained_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Burst power limit +/// +/// @details +/// - The power controller (Punit) will throttle the operating frequency of +/// the device if the power averaged over a few milliseconds exceeds a +/// limit known as PL2. Typically PL2 > PL1 so that it permits the +/// frequency to burst higher for short periods than would be otherwise +/// permitted by PL1. +typedef struct _ctl_power_burst_limit_t +{ + bool enabled; ///< [in,out] indicates if the limit is enabled (true) or ignored (false) + int32_t power; ///< [in,out] power limit in milliwatts + +} ctl_power_burst_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Peak power limit +/// +/// @details +/// - The power controller (Punit) will preemptively throttle the operating +/// frequency of the device when the instantaneous power exceeds this +/// limit. The limit is known as PL4. It expresses the maximum power that +/// can be drawn from the power supply. +/// - If this power limit is removed or set too high, the power supply will +/// generate an interrupt when it detects an overcurrent condition and the +/// power controller will throttle the device frequencies down to min. It +/// is thus better to tune the PL4 value in order to avoid such +/// excursions. +typedef struct _ctl_power_peak_limit_t +{ + int32_t powerAC; ///< [in,out] power limit in milliwatts for the AC power source. + int32_t powerDC; ///< [in,out] power limit in milliwatts for the DC power source. On input, + ///< this is ignored if the product does not have a battery. On output, + ///< this will be -1 if the product does not have a battery. + +} ctl_power_peak_limit_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Power limits +typedef struct _ctl_power_limits_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_power_sustained_limit_t sustainedPowerLimit;///< [in,out] sustained power limit. + ctl_power_burst_limit_t burstPowerLimit; ///< [in,out] burst power limit. + ctl_power_peak_limit_t peakPowerLimits; ///< [in,out] peak power limit. + +} ctl_power_limits_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Energy threshold +/// +/// @details +/// - . +typedef struct _ctl_energy_threshold_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + bool enable; ///< [in,out] Indicates if the energy threshold is enabled. + double threshold; ///< [in,out] The energy threshold in Joules. Will be 0.0 if no threshold + ///< has been set. + uint32_t processId; ///< [in,out] The host process ID that set the energy threshold. Will be + ///< 0xFFFFFFFF if no threshold has been set. + +} ctl_energy_threshold_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of power domains +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumPowerDomains( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_pwr_handle_t* phPower ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get properties related to a power domain +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetProperties( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_properties_t* pProperties ///< [in,out] Structure that will contain property data. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get energy counter +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pEnergy` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetEnergyCounter( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_energy_counter_t* pEnergy ///< [in,out] Will contain the latest snapshot of the energy counter and + ///< timestamp when the last counter value was measured. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get power limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerGetLimits( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + ctl_power_limits_t* pPowerLimits ///< [in,out][optional] Structure that will contain the power limits. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Set power limits +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hPower` +/// - ::CTL_RESULT_ERROR_INSUFFICIENT_PERMISSIONS +/// + User does not have permissions to make these modifications. +/// - ::CTL_RESULT_ERROR_NOT_AVAILABLE +/// + The device is in use, meaning that the GPU is under Over clocking, applying power limits under overclocking is not supported. +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlPowerSetLimits( + ctl_pwr_handle_t hPower, ///< [in] Handle for the component. + const ctl_power_limits_t* pPowerLimits ///< [in][optional] Structure that will contain the power limits. + ); + + +#if !defined(__GNUC__) +#pragma endregion // power +#endif +// Intel 'ctlApi' for Device Adapter - Temperature Sensors +#if !defined(__GNUC__) +#pragma region temperature +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Temperature sensors +typedef enum _ctl_temp_sensors_t +{ + CTL_TEMP_SENSORS_GLOBAL = 0, ///< The maximum temperature across all device sensors + CTL_TEMP_SENSORS_GPU = 1, ///< The maximum temperature across all sensors in the GPU + CTL_TEMP_SENSORS_MEMORY = 2, ///< The maximum temperature across all sensors in the local memory + CTL_TEMP_SENSORS_GLOBAL_MIN = 3, ///< The minimum temperature across all device sensors + CTL_TEMP_SENSORS_GPU_MIN = 4, ///< The minimum temperature across all sensors in the GPU + CTL_TEMP_SENSORS_MEMORY_MIN = 5, ///< The minimum temperature across all sensors in the local device memory + CTL_TEMP_SENSORS_MAX + +} ctl_temp_sensors_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Temperature sensor properties +typedef struct _ctl_temp_properties_t +{ + uint32_t Size; ///< [in] size of this structure + uint8_t Version; ///< [in] version of this structure + ctl_temp_sensors_t type; ///< [out] Which part of the device the temperature sensor measures + double maxTemperature; ///< [out] Will contain the maximum temperature for the specific device in + ///< degrees Celsius. + +} ctl_temp_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get handle of temperature sensors +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hDAhandle` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pCount` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlEnumTemperatureSensors( + ctl_device_adapter_handle_t hDAhandle, ///< [in][release] Handle to display adapter + uint32_t* pCount, ///< [in,out] pointer to the number of components of this type. + ///< if count is zero, then the driver shall update the value with the + ///< total number of components of this type that are available. + ///< if count is greater than the number of components of this type that + ///< are available, then the driver shall update the value with the correct + ///< number of components. + ctl_temp_handle_t* phTemperature ///< [in,out][optional][range(0, *pCount)] array of handle of components of + ///< this type. + ///< if count is less than the number of components of this type that are + ///< available, then the driver shall only retrieve that number of + ///< component handles. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get temperature sensor properties +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hTemperature` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pProperties` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlTemperatureGetProperties( + ctl_temp_handle_t hTemperature, ///< [in] Handle for the component. + ctl_temp_properties_t* pProperties ///< [in,out] Will contain the temperature sensor properties. + ); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Get the temperature from a specified sensor +/// +/// @details +/// - The application may call this function from simultaneous threads. +/// - The implementation of this function should be lock-free. +/// +/// @returns +/// - CTL_RESULT_SUCCESS +/// - CTL_RESULT_ERROR_UNINITIALIZED +/// - CTL_RESULT_ERROR_DEVICE_LOST +/// - CTL_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `nullptr == hTemperature` +/// - CTL_RESULT_ERROR_INVALID_NULL_POINTER +/// + `nullptr == pTemperature` +CTL_APIEXPORT ctl_result_t CTL_APICALL +ctlTemperatureGetState( + ctl_temp_handle_t hTemperature, ///< [in] Handle for the component. + double* pTemperature ///< [in,out] Will contain the temperature read from the specified sensor + ///< in degrees Celsius. + ); + + +#if !defined(__GNUC__) +#pragma endregion // temperature +#endif + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlInit +typedef ctl_result_t (CTL_APICALL *ctl_pfnInit_t)( + ctl_init_args_t*, + ctl_api_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlClose +typedef ctl_result_t (CTL_APICALL *ctl_pfnClose_t)( + ctl_api_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetRuntimePath +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetRuntimePath_t)( + ctl_runtime_path_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlWaitForPropertyChange +typedef ctl_result_t (CTL_APICALL *ctl_pfnWaitForPropertyChange_t)( + ctl_device_adapter_handle_t, + ctl_wait_property_change_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlReservedCall +typedef ctl_result_t (CTL_APICALL *ctl_pfnReservedCall_t)( + ctl_device_adapter_handle_t, + ctl_reserved_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupported3DCapabilities +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupported3DCapabilities_t)( + ctl_device_adapter_handle_t, + ctl_3d_feature_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSet3DFeature +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSet3DFeature_t)( + ctl_device_adapter_handle_t, + ctl_3d_feature_getset_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlCheckDriverVersion +typedef ctl_result_t (CTL_APICALL *ctl_pfnCheckDriverVersion_t)( + ctl_device_adapter_handle_t, + ctl_version_info_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateDevices +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateDevices_t)( + ctl_api_handle_t, + uint32_t*, + ctl_device_adapter_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateDisplayOutputs +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateDisplayOutputs_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_display_output_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateI2CPinPairs +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateI2CPinPairs_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_i2c_pin_pair_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetDeviceProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetDeviceProperties_t)( + ctl_device_adapter_handle_t, + ctl_device_adapter_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetDisplayProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetDisplayProperties_t)( + ctl_display_output_handle_t, + ctl_display_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetAdaperDisplayEncoderProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetAdaperDisplayEncoderProperties_t)( + ctl_display_output_handle_t, + ctl_adapter_display_encoder_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetZeDevice +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetZeDevice_t)( + ctl_device_adapter_handle_t, + void*, + void** + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSharpnessCaps +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSharpnessCaps_t)( + ctl_display_output_handle_t, + ctl_sharpness_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetCurrentSharpness +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetCurrentSharpness_t)( + ctl_display_output_handle_t, + ctl_sharpness_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetCurrentSharpness +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetCurrentSharpness_t)( + ctl_display_output_handle_t, + ctl_sharpness_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlI2CAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnI2CAccess_t)( + ctl_display_output_handle_t, + ctl_i2c_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlI2CAccessOnPinPair +typedef ctl_result_t (CTL_APICALL *ctl_pfnI2CAccessOnPinPair_t)( + ctl_i2c_pin_pair_handle_t, + ctl_i2c_access_pinpair_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlAUXAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnAUXAccess_t)( + ctl_display_output_handle_t, + ctl_aux_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetPowerOptimizationCaps +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetPowerOptimizationCaps_t)( + ctl_display_output_handle_t, + ctl_power_optimization_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetPowerOptimizationSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetPowerOptimizationSetting_t)( + ctl_display_output_handle_t, + ctl_power_optimization_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetPowerOptimizationSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetPowerOptimizationSetting_t)( + ctl_display_output_handle_t, + ctl_power_optimization_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetBrightnessSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetBrightnessSetting_t)( + ctl_display_output_handle_t, + ctl_set_brightness_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetBrightnessSetting +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetBrightnessSetting_t)( + ctl_display_output_handle_t, + ctl_get_brightness_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPixelTransformationGetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnPixelTransformationGetConfig_t)( + ctl_display_output_handle_t, + ctl_pixtx_pipe_get_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPixelTransformationSetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnPixelTransformationSetConfig_t)( + ctl_display_output_handle_t, + ctl_pixtx_pipe_set_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPanelDescriptorAccess +typedef ctl_result_t (CTL_APICALL *ctl_pfnPanelDescriptorAccess_t)( + ctl_display_output_handle_t, + ctl_panel_descriptor_access_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedRetroScalingCapability +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedRetroScalingCapability_t)( + ctl_device_adapter_handle_t, + ctl_retro_scaling_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetRetroScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetRetroScaling_t)( + ctl_device_adapter_handle_t, + ctl_retro_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedScalingCapability +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedScalingCapability_t)( + ctl_display_output_handle_t, + ctl_scaling_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetCurrentScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetCurrentScaling_t)( + ctl_display_output_handle_t, + ctl_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetCurrentScaling +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetCurrentScaling_t)( + ctl_display_output_handle_t, + ctl_scaling_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetLACEConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetLACEConfig_t)( + ctl_display_output_handle_t, + ctl_lace_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetLACEConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetLACEConfig_t)( + ctl_display_output_handle_t, + ctl_lace_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSoftwarePSR +typedef ctl_result_t (CTL_APICALL *ctl_pfnSoftwarePSR_t)( + ctl_display_output_handle_t, + ctl_sw_psr_settings_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetIntelArcSyncInfoForMonitor +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetIntelArcSyncInfoForMonitor_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_monitor_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumerateMuxDevices +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumerateMuxDevices_t)( + ctl_api_handle_t, + uint32_t*, + ctl_mux_output_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetMuxProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetMuxProperties_t)( + ctl_mux_output_handle_t, + ctl_mux_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSwitchMux +typedef ctl_result_t (CTL_APICALL *ctl_pfnSwitchMux_t)( + ctl_mux_output_handle_t, + ctl_display_output_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetIntelArcSyncProfile +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetIntelArcSyncProfile_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_profile_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlSetIntelArcSyncProfile +typedef ctl_result_t (CTL_APICALL *ctl_pfnSetIntelArcSyncProfile_t)( + ctl_display_output_handle_t, + ctl_intel_arc_sync_profile_params_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEdidManagement +typedef ctl_result_t (CTL_APICALL *ctl_pfnEdidManagement_t)( + ctl_display_output_handle_t, + ctl_edid_management_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetCustomMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetCustomMode_t)( + ctl_display_output_handle_t, + ctl_get_set_custom_mode_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetCombinedDisplay +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetCombinedDisplay_t)( + ctl_device_adapter_handle_t, + ctl_combined_display_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetDisplayGenlock +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetDisplayGenlock_t)( + ctl_device_adapter_handle_t*, + ctl_genlock_args_t*, + uint32_t, + ctl_device_adapter_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetVblankTimestamp +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetVblankTimestamp_t)( + ctl_display_output_handle_t, + ctl_vblank_ts_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlLinkDisplayAdapters +typedef ctl_result_t (CTL_APICALL *ctl_pfnLinkDisplayAdapters_t)( + ctl_device_adapter_handle_t, + ctl_lda_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlUnlinkDisplayAdapters +typedef ctl_result_t (CTL_APICALL *ctl_pfnUnlinkDisplayAdapters_t)( + ctl_device_adapter_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetLinkedDisplayAdapters +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetLinkedDisplayAdapters_t)( + ctl_device_adapter_handle_t, + ctl_lda_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetDynamicContrastEnhancement +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetDynamicContrastEnhancement_t)( + ctl_display_output_handle_t, + ctl_dce_args_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumEngineGroups +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumEngineGroups_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_engine_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEngineGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnEngineGetProperties_t)( + ctl_engine_handle_t, + ctl_engine_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEngineGetActivity +typedef ctl_result_t (CTL_APICALL *ctl_pfnEngineGetActivity_t)( + ctl_engine_handle_t, + ctl_engine_stats_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumFans +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumFans_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_fan_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetProperties_t)( + ctl_fan_handle_t, + ctl_fan_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetConfig +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetConfig_t)( + ctl_fan_handle_t, + ctl_fan_config_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetDefaultMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetDefaultMode_t)( + ctl_fan_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetFixedSpeedMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetFixedSpeedMode_t)( + ctl_fan_handle_t, + const ctl_fan_speed_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanSetSpeedTableMode +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanSetSpeedTableMode_t)( + ctl_fan_handle_t, + const ctl_fan_speed_table_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFanGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnFanGetState_t)( + ctl_fan_handle_t, + ctl_fan_speed_units_t, + int32_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumFrequencyDomains +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumFrequencyDomains_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_freq_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetProperties_t)( + ctl_freq_handle_t, + ctl_freq_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetAvailableClocks +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetAvailableClocks_t)( + ctl_freq_handle_t, + uint32_t*, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetRange +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetRange_t)( + ctl_freq_handle_t, + ctl_freq_range_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencySetRange +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencySetRange_t)( + ctl_freq_handle_t, + const ctl_freq_range_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetState_t)( + ctl_freq_handle_t, + ctl_freq_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlFrequencyGetThrottleTime +typedef ctl_result_t (CTL_APICALL *ctl_pfnFrequencyGetThrottleTime_t)( + ctl_freq_handle_t, + ctl_freq_throttle_time_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSupportedVideoProcessingCapabilities +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSupportedVideoProcessingCapabilities_t)( + ctl_device_adapter_handle_t, + ctl_video_processing_feature_caps_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlGetSetVideoProcessingFeature +typedef ctl_result_t (CTL_APICALL *ctl_pfnGetSetVideoProcessingFeature_t)( + ctl_device_adapter_handle_t, + ctl_video_processing_feature_getset_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumMemoryModules +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumMemoryModules_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_mem_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetProperties_t)( + ctl_mem_handle_t, + ctl_mem_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetState_t)( + ctl_mem_handle_t, + ctl_mem_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlMemoryGetBandwidth +typedef ctl_result_t (CTL_APICALL *ctl_pfnMemoryGetBandwidth_t)( + ctl_mem_handle_t, + ctl_mem_bandwidth_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGetProperties_t)( + ctl_device_adapter_handle_t, + ctl_oc_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockWaiverSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockWaiverSet_t)( + ctl_device_adapter_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuFrequencyOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuFrequencyOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuFrequencyOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuFrequencyOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuVoltageOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuVoltageOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuVoltageOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuVoltageOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuLockGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuLockGet_t)( + ctl_device_adapter_handle_t, + ctl_oc_vf_pair_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockGpuLockSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockGpuLockSet_t)( + ctl_device_adapter_handle_t, + ctl_oc_vf_pair_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramFrequencyOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramFrequencyOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramFrequencyOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramFrequencyOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramVoltageOffsetGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramVoltageOffsetGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockVramVoltageOffsetSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockVramVoltageOffsetSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockPowerLimitGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockPowerLimitGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockPowerLimitSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockPowerLimitSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockTemperatureLimitGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockTemperatureLimitGet_t)( + ctl_device_adapter_handle_t, + double* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockTemperatureLimitSet +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockTemperatureLimitSet_t)( + ctl_device_adapter_handle_t, + double + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerTelemetryGet +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerTelemetryGet_t)( + ctl_device_adapter_handle_t, + ctl_power_telemetry_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlOverclockResetToDefault +typedef ctl_result_t (CTL_APICALL *ctl_pfnOverclockResetToDefault_t)( + ctl_device_adapter_handle_t + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPciGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnPciGetProperties_t)( + ctl_device_adapter_handle_t, + ctl_pci_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPciGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnPciGetState_t)( + ctl_device_adapter_handle_t, + ctl_pci_state_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumPowerDomains +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumPowerDomains_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_pwr_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetProperties_t)( + ctl_pwr_handle_t, + ctl_power_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetEnergyCounter +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetEnergyCounter_t)( + ctl_pwr_handle_t, + ctl_power_energy_counter_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerGetLimits +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerGetLimits_t)( + ctl_pwr_handle_t, + ctl_power_limits_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlPowerSetLimits +typedef ctl_result_t (CTL_APICALL *ctl_pfnPowerSetLimits_t)( + ctl_pwr_handle_t, + const ctl_power_limits_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlEnumTemperatureSensors +typedef ctl_result_t (CTL_APICALL *ctl_pfnEnumTemperatureSensors_t)( + ctl_device_adapter_handle_t, + uint32_t*, + ctl_temp_handle_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlTemperatureGetProperties +typedef ctl_result_t (CTL_APICALL *ctl_pfnTemperatureGetProperties_t)( + ctl_temp_handle_t, + ctl_temp_properties_t* + ); + + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for ctlTemperatureGetState +typedef ctl_result_t (CTL_APICALL *ctl_pfnTemperatureGetState_t)( + ctl_temp_handle_t, + double* + ); + + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // _CTL_API_H \ No newline at end of file diff --git a/src/3rdparty/igcl/repo.json b/src/3rdparty/igcl/repo.json new file mode 100644 index 0000000000..5c4bb82be9 --- /dev/null +++ b/src/3rdparty/igcl/repo.json @@ -0,0 +1,6 @@ +{ + "home": "https://github.com/intel/drivers.gpu.control-library", + "license": "README.md", + "version": "e1776b7be2ceead1296204371447b27860d25a66", + "author": "Intel Corporation" +} diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c new file mode 100644 index 0000000000..367acc83ed --- /dev/null +++ b/src/detection/gpu/gpu_intel.c @@ -0,0 +1,152 @@ +#include "gpu_intel.h" + +#include "3rdparty/igcl/igcl_api.h" +#include "common/library.h" + +struct FFIgclData { + FF_LIBRARY_SYMBOL(ctlClose) + + FF_LIBRARY_SYMBOL(ctlEnumerateDevices) + FF_LIBRARY_SYMBOL(ctlGetDeviceProperties) + FF_LIBRARY_SYMBOL(ctlEnumTemperatureSensors) + FF_LIBRARY_SYMBOL(ctlTemperatureGetState) + FF_LIBRARY_SYMBOL(ctlEnumMemoryModules) + FF_LIBRARY_SYMBOL(ctlMemoryGetState) + + bool inited; + ctl_api_handle_t apiHandle; +} igclData; + +static void shutdownIgcl() +{ + if (igclData.apiHandle) + { + igclData.ffctlClose(igclData.apiHandle); + igclData.apiHandle = NULL; + } +} + +const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult result, const char* soName) +{ + if (!igclData.inited) + { + igclData.inited = true; + FF_LIBRARY_LOAD(libigcl, NULL, "dlopen igcl (ControlLib) failed", soName , 1); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libigcl, ctlInit) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlClose) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumerateDevices) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlGetDeviceProperties) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumTemperatureSensors) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlTemperatureGetState) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumMemoryModules) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState) + + if (ffctlInit(&(ctl_init_args_t) { + .AppVersion = CTL_MAKE_VERSION(CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION), + .flags = CTL_INIT_FLAG_USE_LEVEL_ZERO, + .Size = sizeof(ctl_init_args_t), + .Version = 0, + }, &igclData.apiHandle) != CTL_RESULT_SUCCESS) + return "loading igcl library failed"; + atexit(shutdownIgcl); + libigcl = NULL; // don't close igcl + } + + if (!igclData.apiHandle) + return "loading igcl library failed"; + + uint32_t deviceCount = 0; + if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, NULL)) + return "ctlEnumerateDevices(NULL) failed"; + ctl_device_adapter_handle_t devices[16] = {}; + if (deviceCount == 0 || deviceCount > sizeof(devices) / sizeof(devices[0])) + return "Invalid device count"; + if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, devices)) + return "ctlEnumerateDevices(devices) failed"; + + ctl_device_adapter_handle_t device = NULL; + + LUID deviceId; + ctl_device_adapter_properties_t properties = { + .Size = sizeof(properties), + .pDeviceID = &deviceId, + .device_id_size = sizeof(deviceId), + .Version = 2, + }; + for (uint32_t iDev = 0; iDev < deviceCount; iDev++) + { + if (igclData.ffctlGetDeviceProperties(devices[iDev], &properties) != CTL_RESULT_SUCCESS) + continue; + + if (properties.device_type != CTL_DEVICE_TYPE_GRAPHICS) + continue; + + if ( + cond.pciDeviceId == properties.pci_device_id && + cond.pciVendorId == properties.pci_vendor_id && + cond.pciSubSystemId == (((uint32_t) properties.pci_subsys_id << 16u) + (uint32_t) properties.pci_subsys_vendor_id) && + cond.revId == properties.rev_id) + { + device = devices[iDev]; + break; + } + } + + if (!device) + return "Device not found"; + + if (result.coreCount) + *result.coreCount = properties.num_slices * properties.num_sub_slices_per_slice * properties.num_eus_per_sub_slice; + + if (result.memory) + { + ctl_mem_handle_t memoryModules[16]; + uint32_t memoryCount = sizeof(memoryModules) / sizeof(memoryModules[0]); + if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS) + { + result.memory->used = 0; + result.memory->total = 0; + for (uint32_t iMem = 0; iMem < memoryCount; iMem++) + { + ctl_mem_state_t memoryState = { + .Size = sizeof(ctl_mem_state_t), + .Version = 0, + }; + if (igclData.ffctlMemoryGetState(memoryModules[iMem], &memoryState) == CTL_RESULT_SUCCESS) + { + result.memory->total += memoryState.size; + result.memory->used += memoryState.size - memoryState.free; + } + } + } + } + + if (result.type) + { + *result.type = properties.graphics_adapter_properties & CTL_ADAPTER_PROPERTIES_FLAG_INTEGRATED + ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + } + + if (result.temp) + { + ctl_temp_handle_t sensors[16]; + uint32_t sensorCount = sizeof(sensors) / sizeof(sensors[0]); + if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS) + { + double sumValue = 0; + uint32_t availableCount = 0; + for (uint32_t iSensor = 0; iSensor < sensorCount; iSensor++) + { + double value; + if (igclData.ffctlTemperatureGetState(sensors[iSensor], &value) == CTL_RESULT_SUCCESS) + { + sumValue += value; + availableCount++; + } + } + *result.temp = sumValue / availableCount; + } + } + + return NULL; +} diff --git a/src/detection/gpu/gpu_intel.h b/src/detection/gpu/gpu_intel.h new file mode 100644 index 0000000000..ad9d5040df --- /dev/null +++ b/src/detection/gpu/gpu_intel.h @@ -0,0 +1,23 @@ +#pragma once + +#include "gpu.h" + +// Use pciBusId if not NULL; use pciDeviceId and pciSubSystemId otherwise +typedef struct FFGpuIntelCondition +{ + uint32_t pciDeviceId; + uint32_t pciVendorId; + uint32_t pciSubSystemId; + uint32_t revId; +} FFGpuIntelCondition; + +// detect x if not NULL +typedef struct FFGpuIntelResult +{ + double* temp; + FFGPUMemory* memory; + uint32_t* coreCount; + FFGPUType* type; +} FFGpuIntelResult; + +const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult result, const char* soName); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 8f1fac03a5..be2ffddb91 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -1,4 +1,5 @@ #include "gpu.h" +#include "detection/gpu/gpu_intel.h" #include "detection/gpu/gpu_nvidia.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" @@ -102,6 +103,33 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }, "nvml.dll"); } } + + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL && (options->temp || options->useNvml)) + { + uint32_t vendorId, deviceId, subSystemId, revId; + // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html + // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_8086&DEV_46A6&SUBSYS_13241462&REV_0C" + if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) + { + ffDetectIntelGpuInfo((FFGpuIntelCondition) { + .pciDeviceId = deviceId, + .pciVendorId = vendorId, + .pciSubSystemId = subSystemId, + .revId = revId, + }, (FFGpuIntelResult) { + .temp = options->temp ? &gpu->temperature : NULL, + .memory = options->useNvml ? &gpu->dedicated : NULL, + .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, + }, + #ifdef _WIN64 + "ControlLib.dll" + #else + "ControlLib32.dll" + #endif + ); + } + } } return NULL; From 4a1bbb6a03f04229db8fef0955e67c258a8f15d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 14:45:27 +0800 Subject: [PATCH 06/81] GPU: huge improvement of driver specific detection code --- src/detection/gpu/gpu.h | 6 ++- src/detection/gpu/gpu_apple.c | 1 + src/detection/gpu/gpu_driver_specific.h | 48 ++++++++++++++++++ src/detection/gpu/gpu_intel.c | 48 ++++++++++++++---- src/detection/gpu/gpu_intel.h | 23 --------- src/detection/gpu/gpu_linux.c | 18 +++++-- src/detection/gpu/gpu_nvidia.c | 21 +++++--- src/detection/gpu/gpu_nvidia.h | 23 --------- src/detection/gpu/gpu_windows.c | 67 +++++++++++-------------- src/detection/gpu/gpu_wsl.cpp | 17 +++++-- src/detection/vulkan/vulkan.c | 5 +- src/modules/gpu/gpu.c | 11 +++- src/modules/vulkan/vulkan.c | 2 +- 13 files changed, 174 insertions(+), 116 deletions(-) create mode 100644 src/detection/gpu/gpu_driver_specific.h delete mode 100644 src/detection/gpu/gpu_intel.h delete mode 100644 src/detection/gpu/gpu_nvidia.h diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 9c73637cc9..c8efcd66cd 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -5,6 +5,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) +#define FF_GPU_FREQUENCY_UNSET -1u extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -29,10 +30,11 @@ typedef struct FFGPUResult FFstrbuf name; FFstrbuf driver; double temperature; - int coreCount; + int32_t coreCount; + uint32_t frequency; FFGPUMemory dedicated; FFGPUMemory shared; - uint32_t vulkanDeviceId; // Only used for vulkan + uint64_t deviceId; // Used internally, may be uninitialized } FFGPUResult; const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result); diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index bb734596d2..bed5586310 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -54,6 +54,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver); diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h new file mode 100644 index 0000000000..3049958baf --- /dev/null +++ b/src/detection/gpu/gpu_driver_specific.h @@ -0,0 +1,48 @@ +#pragma once + +#include "gpu.h" + +typedef enum FFGpuDriverConditionType +{ + FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID = 1 << 0, + FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID = 1 << 1, + FF_GPU_DRIVER_CONDITION_TYPE_LUID = 1 << 2, +} FFGpuDriverConditionType; + +typedef struct FFGpuDriverPciBusId +{ + uint32_t domain; + uint32_t bus; + uint32_t device; + uint32_t func; +} FFGpuDriverPciBusId; + +typedef struct FFGpuDriverPciDeviceId +{ + uint32_t deviceId; + uint32_t vendorId; + uint32_t subSystemId; + uint32_t revId; +} FFGpuDriverPciDeviceId; + +// Use pciBusId if not NULL; use pciDeviceId otherwise +typedef struct FFGpuDriverCondition +{ + FFGpuDriverConditionType type; + FFGpuDriverPciBusId pciBusId; + FFGpuDriverPciDeviceId pciDeviceId; + uint64_t luid; +} FFGpuDriverCondition; + +// detect x if not NULL +typedef struct FFGpuDriverResult +{ + double* temp; + FFGPUMemory* memory; + uint32_t* coreCount; + FFGPUType* type; + uint32_t* frequency; +} FFGpuDriverResult; + +const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); +const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 367acc83ed..6b131c557d 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -1,4 +1,4 @@ -#include "gpu_intel.h" +#include "gpu_driver_specific.h" #include "3rdparty/igcl/igcl_api.h" #include "common/library.h" @@ -12,6 +12,8 @@ struct FFIgclData { FF_LIBRARY_SYMBOL(ctlTemperatureGetState) FF_LIBRARY_SYMBOL(ctlEnumMemoryModules) FF_LIBRARY_SYMBOL(ctlMemoryGetState) + FF_LIBRARY_SYMBOL(ctlEnumFrequencyDomains) + FF_LIBRARY_SYMBOL(ctlFrequencyGetState) bool inited; ctl_api_handle_t apiHandle; @@ -26,7 +28,7 @@ static void shutdownIgcl() } } -const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult result, const char* soName) +const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) { if (!igclData.inited) { @@ -40,6 +42,8 @@ const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult resu FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlTemperatureGetState) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumMemoryModules) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlMemoryGetState) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlEnumFrequencyDomains) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libigcl, igclData, ctlFrequencyGetState) if (ffctlInit(&(ctl_init_args_t) { .AppVersion = CTL_MAKE_VERSION(CTL_IMPL_MAJOR_VERSION, CTL_IMPL_MINOR_VERSION), @@ -66,7 +70,7 @@ const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult resu ctl_device_adapter_handle_t device = NULL; - LUID deviceId; + uint64_t /* LUID */ deviceId = 0; ctl_device_adapter_properties_t properties = { .Size = sizeof(properties), .pDeviceID = &deviceId, @@ -81,14 +85,35 @@ const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult resu if (properties.device_type != CTL_DEVICE_TYPE_GRAPHICS) continue; - if ( - cond.pciDeviceId == properties.pci_device_id && - cond.pciVendorId == properties.pci_vendor_id && - cond.pciSubSystemId == (((uint32_t) properties.pci_subsys_id << 16u) + (uint32_t) properties.pci_subsys_vendor_id) && - cond.revId == properties.rev_id) + if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_LUID) { - device = devices[iDev]; - break; + if (cond->luid == deviceId) + { + device = devices[iDev]; + break; + } + } + else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) + { + if (cond->pciBusId.bus == properties.adapter_bdf.bus && + cond->pciBusId.device == properties.adapter_bdf.device && + cond->pciBusId.func == properties.adapter_bdf.function) + { + device = devices[iDev]; + break; + } + } + else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) + { + if ( + cond->pciDeviceId.deviceId == properties.pci_device_id && + cond->pciDeviceId.vendorId == properties.pci_vendor_id && + cond->pciDeviceId.subSystemId == (uint32_t) ((properties.pci_subsys_id << 16u) | properties.pci_subsys_vendor_id) && + cond->pciDeviceId.revId == properties.rev_id) + { + device = devices[iDev]; + break; + } } } @@ -148,5 +173,8 @@ const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult resu } } + if (result.frequency) + *result.frequency = properties.Frequency; + return NULL; } diff --git a/src/detection/gpu/gpu_intel.h b/src/detection/gpu/gpu_intel.h deleted file mode 100644 index ad9d5040df..0000000000 --- a/src/detection/gpu/gpu_intel.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "gpu.h" - -// Use pciBusId if not NULL; use pciDeviceId and pciSubSystemId otherwise -typedef struct FFGpuIntelCondition -{ - uint32_t pciDeviceId; - uint32_t pciVendorId; - uint32_t pciSubSystemId; - uint32_t revId; -} FFGpuIntelCondition; - -// detect x if not NULL -typedef struct FFGpuIntelResult -{ - double* temp; - FFGPUMemory* memory; - uint32_t* coreCount; - FFGPUType* type; -} FFGpuIntelResult; - -const char* ffDetectIntelGpuInfo(FFGpuIntelCondition cond, FFGpuIntelResult result, const char* soName); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 819f3e7a4c..094d9c4dc6 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -1,5 +1,5 @@ #include "detection/gpu/gpu.h" -#include "detection/gpu/gpu_nvidia.h" +#include "detection/gpu/gpu_driver_specific.h" #include "detection/vulkan/vulkan.h" #ifdef FF_HAVE_LIBPCI @@ -239,16 +239,24 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml)) { - char pciDeviceId[32]; - snprintf(pciDeviceId, sizeof(pciDeviceId) - 1, "%04x:%02x:%02x.%d", device->domain, device->bus, device->dev, device->func); - - ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) { .pciBusId = pciDeviceId }, (FFGpuNvidiaResult) { + ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { + .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, + .pciDeviceId = { + .domain = device->domain, + .bus = device->bus, + .device = device->dev, + .func = device->func, + }, + }, (FFGpuNvidiaResult) { .temp = options->temp ? &gpu->temperature : NULL, .memory = options->useNvml ? &gpu->dedicated : NULL, .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, + .frequency = options->useNvml ? &gpu->frequency : NULL, }, "libnvidia-ml.so"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 214f0b992e..1bbddd2c74 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -1,4 +1,4 @@ -#include "gpu_nvidia.h" +#include "gpu_driver_specific.h" #include "3rdparty/nvml/nvml.h" #include "common/library.h" @@ -11,11 +11,12 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature) FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2) FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores) + FF_LIBRARY_SYMBOL(nvmlDeviceGetClockInfo) bool inited; } nvmlData; -const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName) +const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) { if (!nvmlData.inited) { @@ -30,6 +31,7 @@ const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult r FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetClockInfo) if (ffnvmlInit_v2() != NVML_SUCCESS) { @@ -44,13 +46,16 @@ const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult r return "loading nvml library failed"; nvmlDevice_t device = NULL; - if (cond.pciBusId) + if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID) { - nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(cond.pciBusId, &device); + char pciBusIdStr[32]; + snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func); + + nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(pciBusIdStr, &device); if (ret != NVML_SUCCESS) return "nvmlDeviceGetHandleByPciBusId_v2() failed"; } - else + else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) { uint32_t count; if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS) @@ -65,7 +70,8 @@ const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult r if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS) continue; - if (pciInfo.pciDeviceId != cond.pciDeviceId || pciInfo.pciSubSystemId != cond.pciSubSystemId) + if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) || + pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId) continue; break; @@ -93,5 +99,8 @@ const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult r if (result.coreCount) nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount); + if (result.frequency) + nvmlData.ffnvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency); + return NULL; } diff --git a/src/detection/gpu/gpu_nvidia.h b/src/detection/gpu/gpu_nvidia.h deleted file mode 100644 index bce84aa8d8..0000000000 --- a/src/detection/gpu/gpu_nvidia.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "gpu.h" - -// Use pciBusId if not NULL; use pciDeviceId and pciSubSystemId otherwise -typedef struct FFGpuNvidiaCondition -{ - // "domain:bus:device.function" - const char* pciBusId; - // (deviceId << 16) | vendorId - uint32_t pciDeviceId; - uint32_t pciSubSystemId; -} FFGpuNvidiaCondition; - -// detect x if not NULL -typedef struct FFGpuNvidiaResult -{ - double* temp; - FFGPUMemory* memory; - uint32_t* coreCount; -} FFGpuNvidiaResult; - -const char* ffDetectNvidiaGpuInfo(FFGpuNvidiaCondition cond, FFGpuNvidiaResult result, const char* soName); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index be2ffddb91..f56b87a1fd 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -1,6 +1,5 @@ #include "gpu.h" -#include "detection/gpu/gpu_intel.h" -#include "detection/gpu/gpu_nvidia.h" +#include "detection/gpu/gpu_driver_specific.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" @@ -44,6 +43,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = 0; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (deviceKeyLength == 100 && displayDevice.DeviceKey[deviceKeyPrefixLength - 1] == '{') { @@ -76,6 +77,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->dedicated.total = dedicatedVideoMemory + dedicatedSystemMemory; gpu->shared.total = sharedSystemMemory; } + + ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); } else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) { @@ -86,47 +89,35 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } } - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml)) - { - uint32_t vendorId, deviceId, subSystemId; - // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html - // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" - if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendorId, &deviceId, &subSystemId) == 3) - { - ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) { - .pciDeviceId = (deviceId << 16) | vendorId, - .pciSubSystemId = subSystemId, - }, (FFGpuNvidiaResult) { - .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->useNvml ? &gpu->dedicated : NULL, - .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, - }, "nvml.dll"); - } - } - - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL && (options->temp || options->useNvml)) + if ((gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA || gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) && + (options->temp || options->useNvml)) { uint32_t vendorId, deviceId, subSystemId, revId; // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html - // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_8086&DEV_46A6&SUBSYS_13241462&REV_0C" + // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) { - ffDetectIntelGpuInfo((FFGpuIntelCondition) { - .pciDeviceId = deviceId, - .pciVendorId = vendorId, - .pciSubSystemId = subSystemId, - .revId = revId, - }, (FFGpuIntelResult) { - .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->useNvml ? &gpu->dedicated : NULL, - .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, - }, - #ifdef _WIN64 - "ControlLib.dll" - #else - "ControlLib32.dll" - #endif + (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? ffDetectNvidiaGpuInfo : ffDetectIntelGpuInfo)( + &(FFGpuDriverCondition) { + .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID, + .pciDeviceId = { + .deviceId = deviceId, + .vendorId = vendorId, + .subSystemId = subSystemId, + .revId = revId, + }, + }, (FFGpuDriverResult) { + .temp = options->temp ? &gpu->temperature : NULL, + .memory = options->useNvml ? &gpu->dedicated : NULL, + .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, + .frequency = options->useNvml ? &gpu->frequency : NULL, + }, gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? "nvml.dll" : + #ifdef _WIN64 + "ControlLib.dll" + #else + "ControlLib32.dll" + #endif ); } } diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index a2a01fc144..8f8af9f078 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -4,7 +4,7 @@ extern "C" { #include "common/library.h" #include "detection/gpu/gpu.h" -#include "detection/gpu/gpu_nvidia.h" +#include "detection/gpu/gpu_driver_specific.h" } #include @@ -65,6 +65,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF ffStrbufInitS(&gpu->name, desc); gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; ffStrbufInit(&gpu->driver); uint64_t value = 0; @@ -97,14 +98,20 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->useNvml) { - ffDetectNvidiaGpuInfo((FFGpuNvidiaCondition) { - .pciBusId = nullptr, - .pciDeviceId = (hardwareId.deviceID << 16) | hardwareId.vendorID, - .pciSubSystemId = hardwareId.subSysID + ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { + .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID, + .pciDeviceId = { + .deviceId = hardwareId.deviceID, + .vendorId = hardwareId.vendorID, + .subSystemId = hardwareId.subSysID, + .revId = hardwareId.revision, + }, }, (FFGpuNvidiaResult) { .temp = options->temp ? &gpu->temperature : NULL, .memory = options->useNvml ? &gpu->dedicated : NULL, .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, + .frequency = options->useNvml ? &gpu->frequency : NULL, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); } } diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 8cd4aed657..5d7fe431b0 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -175,13 +175,13 @@ static const char* detectVulkan(FFVulkanResult* result) // #456 FF_LIST_FOR_EACH(FFGPUResult, gpu, result->gpus) { - if (gpu->vulkanDeviceId == physicalDeviceProperties.properties.deviceID) + if (gpu->deviceId == physicalDeviceProperties.properties.deviceID) goto next; } FFGPUResult* gpu = ffListAdd(&result->gpus); - gpu->vulkanDeviceId = physicalDeviceProperties.properties.deviceID; + gpu->deviceId = physicalDeviceProperties.properties.deviceID; ffStrbufInitS(&gpu->name, physicalDeviceProperties.properties.deviceName); @@ -204,6 +204,7 @@ static const char* detectVulkan(FFVulkanResult* result) //No way to detect those using vulkan gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; next: continue; diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 0e2fdbd8b0..3d02eb4d99 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -9,7 +9,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 10 +#define FF_GPU_NUM_FORMAT_ARGS 11 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -38,6 +38,9 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu if(gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) ffStrbufAppendF(&output, " (%d)", gpu->coreCount); + if(gpu->frequency != FF_GPU_FREQUENCY_UNSET) + ffStrbufAppendF(&output, " @ %.2f MHz", gpu->frequency / 1e6); + if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET { ffStrbufAppendS(&output, " - "); @@ -80,6 +83,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used}, + {FF_FORMAT_ARG_TYPE_UINT, &gpu->frequency}, }); } } @@ -304,6 +308,11 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_str(doc, obj, "type", type); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &gpu->vendor); + + if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) + yyjson_mut_obj_add_null(doc, obj, "frequency"); + else + yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency); } FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) diff --git a/src/modules/vulkan/vulkan.c b/src/modules/vulkan/vulkan.c index 3af0fbe8e5..94a0c32ddf 100644 --- a/src/modules/vulkan/vulkan.c +++ b/src/modules/vulkan/vulkan.c @@ -130,7 +130,7 @@ void ffGenerateVulkanJsonResult(FF_MAYBE_UNUSED FFVulkanOptions* options, yyjson yyjson_mut_obj_add_null(doc, sharedMemory, "used"); } - yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->vulkanDeviceId); + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", vulkanGpu->deviceId); } } From f8be6322df60338996ffbc21d6954e2db183f736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 14:59:27 +0800 Subject: [PATCH 07/81] GPU: rename `use-nvml` to `driver-specific` Because we are supporting drivers other than NVML --- doc/json_schema.json | 4 ++-- src/data/help.json | 6 +++--- src/detection/gpu/gpu_linux.c | 16 ++++++++-------- src/detection/gpu/gpu_windows.c | 10 +++++----- src/detection/gpu/gpu_wsl.cpp | 17 ++++++++++------- src/modules/gpu/gpu.c | 14 +++++++------- src/modules/gpu/option.h | 2 +- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index 7b5516411b..9da9dc902a 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1191,8 +1191,8 @@ "type": "boolean", "default": false }, - "useNvml": { - "description": "Use nvml (NVIDIA Management Library) to detect more detailed GPU information (memory usage, CUDA core count, etc)", + "driverSpecific": { + "description": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)", "type": "boolean", "default": false }, diff --git a/src/data/help.json b/src/data/help.json index 32f6ba73ed..f30c5ed5b7 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1082,9 +1082,9 @@ } }, { - "long": "gpu-use-nvml", - "desc": "Use nvml (NVIDIA Management Library) to detect more detailed GPU information", - "remark": "Detects memory usage, CUDA core count, etc. Requires NVIDIA proprietary driver installed", + "long": "gpu-driver-specific", + "desc": "Use driver specific method to detect more detailed GPU information (memory usage, core count, etc)", + "remark": "Correctly NVML (NVIDIA) and IGCL (Intel, Windows only) are supported. Both require the latest proprietary driver to be installed", "arg": { "type": "bool", "optional": true, diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 094d9c4dc6..630f12ead1 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -241,22 +241,22 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->temperature = FF_GPU_TEMP_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->useNvml)) + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID, - .pciDeviceId = { - .domain = device->domain, + .pciBusId = { + .domain = (uint32_t) device->domain, .bus = device->bus, .device = device->dev, .func = device->func, }, - }, (FFGpuNvidiaResult) { + }, (FFGpuDriverResult) { .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->useNvml ? &gpu->dedicated : NULL, - .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, - .frequency = options->useNvml ? &gpu->frequency : NULL, + .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->driverSpecific ? &gpu->type : NULL, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, "libnvidia-ml.so"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index f56b87a1fd..3d27a7ba3d 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -90,7 +90,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } if ((gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA || gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) && - (options->temp || options->useNvml)) + (options->temp || options->driverSpecific)) { uint32_t vendorId, deviceId, subSystemId, revId; // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html @@ -108,10 +108,10 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }, }, (FFGpuDriverResult) { .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->useNvml ? &gpu->dedicated : NULL, - .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, - .frequency = options->useNvml ? &gpu->frequency : NULL, + .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->driverSpecific ? &gpu->type : NULL, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? "nvml.dll" : #ifdef _WIN64 "ControlLib.dll" diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index 8f8af9f078..117eb2ceef 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -14,6 +14,8 @@ extern "C" { #include #include +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" + template struct on_scope_exit { on_scope_exit(Fn &&fn): _fn(std::move(fn)) {} @@ -96,9 +98,9 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID); ffStrbufSetStatic(&gpu->vendor, vendorStr); - if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->useNvml) + if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->driverSpecific) { - ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { + FFGpuDriverCondition cond = { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID, .pciDeviceId = { .deviceId = hardwareId.deviceID, @@ -106,12 +108,13 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .subSystemId = hardwareId.subSysID, .revId = hardwareId.revision, }, - }, (FFGpuNvidiaResult) { + }; + ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult) { .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->useNvml ? &gpu->dedicated : NULL, - .coreCount = options->useNvml ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->useNvml ? (uint32_t*) &gpu->type : NULL, - .frequency = options->useNvml ? &gpu->frequency : NULL, + .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .type = options->driverSpecific ? &gpu->type : NULL, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); } } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 3d02eb4d99..a159764efa 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -133,9 +133,9 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) return true; - if (ffStrEqualsIgnCase(subKey, "use-nvml")) + if (ffStrEqualsIgnCase(subKey, "driver-specific")) { - options->useNvml = ffOptionParseBoolean(value); + options->driverSpecific = ffOptionParseBoolean(value); return true; } @@ -183,9 +183,9 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) continue; } - if (ffStrEqualsIgnCase(key, "useNvml")) + if (ffStrEqualsIgnCase(key, "driverSpecific")) { - options->useNvml = yyjson_get_bool(val); + options->driverSpecific = yyjson_get_bool(val); continue; } @@ -222,8 +222,8 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); - if (options->useNvml != defaultOptions.useNvml) - yyjson_mut_obj_add_bool(doc, module, "useNvml", options->useNvml); + if (options->driverSpecific != defaultOptions.driverSpecific) + yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific); if (options->forceVulkan != defaultOptions.forceVulkan) yyjson_mut_obj_add_bool(doc, module, "forceVulkan", options->forceVulkan); @@ -354,7 +354,7 @@ void ffInitGPUOptions(FFGPUOptions* options) ); ffOptionInitModuleArg(&options->moduleArgs); - options->useNvml = false; + options->driverSpecific = false; options->forceVulkan = false; options->temp = false; options->hideType = FF_GPU_TYPE_UNKNOWN; diff --git a/src/modules/gpu/option.h b/src/modules/gpu/option.h index 6aa34a9fe4..77babf4373 100644 --- a/src/modules/gpu/option.h +++ b/src/modules/gpu/option.h @@ -18,6 +18,6 @@ typedef struct FFGPUOptions FFGPUType hideType; bool temp; - bool useNvml; + bool driverSpecific; bool forceVulkan; } FFGPUOptions; From a4f5a9af034110e8b44d2ef4d67474490b626a99 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 20 Dec 2023 16:44:30 +0800 Subject: [PATCH 08/81] Brightness (Linux): show meaningfull name on asahi --- src/detection/brightness/brightness_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/brightness/brightness_linux.c b/src/detection/brightness/brightness_linux.c index 55ad476434..266e72702c 100644 --- a/src/detection/brightness/brightness_linux.c +++ b/src/detection/brightness/brightness_linux.c @@ -58,9 +58,9 @@ static const char* detectWithBacklight(FFlist* result) { ffStrbufSubstrBeforeLastC(&brightness->name, '/'); // remove "/edid" ffStrbufSubstrAfterLastC(&brightness->name, '/'); // try getting DRM connector name - if(ffStrbufStartsWithS(&brightness->name, "0000:")) + if(isdigit(brightness->name.chars[0])) { - // PCI address, give up + // PCI address or some unknown path, give up ffStrbufSetS(&brightness->name, entry->d_name); } else From b9368ac20d95a489ae58ff468c131045606d6e07 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Wed, 20 Dec 2023 16:41:24 +0900 Subject: [PATCH 09/81] feature(IO): support searching user's config file from configDirs --- src/common/io/io.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/common/io/io.h b/src/common/io/io.h index 257e9ce831..ec3375bd01 100644 --- a/src/common/io/io.h +++ b/src/common/io/io.h @@ -1,6 +1,7 @@ #pragma once #include "util/FFstrbuf.h" +#include "util/FFlist.h" #ifdef _WIN32 #include @@ -185,3 +186,18 @@ static inline bool wrapClosedir(HANDLE* pdir) } #endif #define FF_AUTO_CLOSE_DIR __attribute__((__cleanup__(wrapClosedir))) + +static inline bool ffSearchUserConfigFile(const FFlist* configDirs, const char* fileSubpath, FFstrbuf* result) +{ + // configDirs is a list of FFstrbufs include the trailing slash + FF_LIST_FOR_EACH(FFstrbuf, dir, *configDirs) + { + ffStrbufClear(result); + ffStrbufAppend(result, dir); + ffStrbufAppendS(result, fileSubpath); + if (ffPathExists(result->chars, FF_PATHTYPE_FILE)) + return true; + } + + return false; +} From 3040bc38cbb19a747e592d0f8d13ef9574edaed7 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Wed, 20 Dec 2023 16:43:35 +0900 Subject: [PATCH 10/81] refactor(WMTheme): use ffSearchUserConfigFile --- src/detection/wmtheme/wmtheme_linux.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/detection/wmtheme/wmtheme_linux.c b/src/detection/wmtheme/wmtheme_linux.c index 1142fc1e6f..7c382f32cc 100644 --- a/src/detection/wmtheme/wmtheme_linux.c +++ b/src/detection/wmtheme/wmtheme_linux.c @@ -133,15 +133,17 @@ static bool detectXFWM4(FFstrbuf* themeOrError) static bool detectOpenbox(const FFstrbuf* dePrettyName, FFstrbuf* themeOrError) { FF_STRBUF_AUTO_DESTROY absolutePath = ffStrbufCreateA(64); - ffStrbufAppend(&absolutePath, &instance.state.platform.homeDir); - - //TODO: use config dirs - if(ffStrbufIgnCaseCompS(dePrettyName, "LXQT") == 0) - ffStrbufAppendS(&absolutePath, ".config/openbox/lxqt-rc.xml"); - else if(ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0) - ffStrbufAppendS(&absolutePath, ".config/openbox/lxde-rc.xml"); - else - ffStrbufAppendS(&absolutePath, ".config/openbox/rc.xml"); + const char *configFileSubpath = "openbox/rc.xml"; + if (ffStrbufIgnCaseCompS(dePrettyName, "LXQT") == 0) + configFileSubpath = "openbox/lxqt-rc.xml"; + else if (ffStrbufIgnCaseCompS(dePrettyName, "LXDE") == 0) + configFileSubpath = "openbox/lxde-rc.xml"; + + if (!ffSearchUserConfigFile(&instance.state.platform.configDirs, configFileSubpath, &absolutePath)) + { + ffStrbufAppendF(themeOrError, "Couldn't find config file \"%s\"", configFileSubpath); + return false; + } FF_STRBUF_AUTO_DESTROY content = ffStrbufCreate(); if (!ffReadFileBuffer(absolutePath.chars, &content)) From b2236cc046f1e6119f70636d255868adac14b87a Mon Sep 17 00:00:00 2001 From: apocelipes Date: Wed, 20 Dec 2023 16:45:53 +0900 Subject: [PATCH 11/81] refactor(TerminalFont): use ffSearchUserConfigFile --- src/detection/terminalfont/terminalfont_linux.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index f320f50e3e..a8fc901bb1 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -172,10 +172,9 @@ static void detectDeepinTerminal(FFTerminalFontResult* terminalFont) { FF_STRBUF_AUTO_DESTROY fontName = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY fontSize = ffStrbufCreate(); - FF_STRBUF_AUTO_DESTROY profile = ffStrbufCreate(); - ffStrbufAppend(&profile, &instance.state.platform.homeDir); - ffStrbufAppendS(&profile, ".config/deepin/deepin-terminal/config.conf"); //TODO: Use config dirs + FF_STRBUF_AUTO_DESTROY profile = ffStrbufCreateA(64); + ffSearchUserConfigFile(&instance.state.platform.configDirs, "deepin/deepin-terminal/config.conf", &profile); FILE* file = fopen(profile.chars, "r"); if(file) From adc506d2b32cbea5cd5845489068ecbc15dea0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 19:09:18 +0800 Subject: [PATCH 12/81] GPU: fix clock frequency detection and overall tidy --- src/detection/cpu/cpu.h | 4 ++-- src/detection/gpu/gpu.h | 4 ++-- src/detection/gpu/gpu_driver_specific.h | 2 +- src/detection/gpu/gpu_intel.c | 14 ++++++++------ src/detection/gpu/gpu_linux.c | 4 ++-- src/detection/gpu/gpu_nvidia.c | 6 +++++- src/detection/gpu/gpu_windows.c | 5 +++-- src/detection/gpu/gpu_wsl.cpp | 4 ++-- src/modules/gpu/gpu.c | 8 ++++---- 9 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 9ae3648086..9586e686e0 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -13,8 +13,8 @@ typedef struct FFCPUResult uint16_t coresLogical; uint16_t coresOnline; - double frequencyMin; - double frequencyMax; + double frequencyMin; // GHz + double frequencyMax; // GHz double temperature; } FFCPUResult; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index c8efcd66cd..23ebcc7f24 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -5,7 +5,7 @@ #define FF_GPU_TEMP_UNSET (0/0.0) #define FF_GPU_CORE_COUNT_UNSET -1 #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) -#define FF_GPU_FREQUENCY_UNSET -1u +#define FF_GPU_FREQUENCY_UNSET (0/0.0) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -31,7 +31,7 @@ typedef struct FFGPUResult FFstrbuf driver; double temperature; int32_t coreCount; - uint32_t frequency; + double frequency; // Real time clock frequency in GHz FFGPUMemory dedicated; FFGPUMemory shared; uint64_t deviceId; // Used internally, may be uninitialized diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 3049958baf..9205c0954b 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -41,7 +41,7 @@ typedef struct FFGpuDriverResult FFGPUMemory* memory; uint32_t* coreCount; FFGPUType* type; - uint32_t* frequency; + double* frequency; } FFGpuDriverResult; const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 6b131c557d..4b67c6eb3e 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -2,6 +2,7 @@ #include "3rdparty/igcl/igcl_api.h" #include "common/library.h" +#include "util/mallocHelper.h" struct FFIgclData { FF_LIBRARY_SYMBOL(ctlClose) @@ -62,9 +63,10 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe uint32_t deviceCount = 0; if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, NULL)) return "ctlEnumerateDevices(NULL) failed"; - ctl_device_adapter_handle_t devices[16] = {}; - if (deviceCount == 0 || deviceCount > sizeof(devices) / sizeof(devices[0])) - return "Invalid device count"; + if (deviceCount == 0) + return "No Intel graphics adapter found"; + + FF_AUTO_FREE ctl_device_adapter_handle_t* devices = malloc(deviceCount * sizeof(*devices)); if (igclData.ffctlEnumerateDevices(igclData.apiHandle, &deviceCount, devices)) return "ctlEnumerateDevices(devices) failed"; @@ -127,7 +129,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe { ctl_mem_handle_t memoryModules[16]; uint32_t memoryCount = sizeof(memoryModules) / sizeof(memoryModules[0]); - if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS) + if (igclData.ffctlEnumMemoryModules(device, &memoryCount, memoryModules) == CTL_RESULT_SUCCESS && memoryCount > 0) { result.memory->used = 0; result.memory->total = 0; @@ -156,7 +158,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe { ctl_temp_handle_t sensors[16]; uint32_t sensorCount = sizeof(sensors) / sizeof(sensors[0]); - if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS) + if (igclData.ffctlEnumTemperatureSensors(device, &sensorCount, sensors) == CTL_RESULT_SUCCESS && sensorCount > 0) { double sumValue = 0; uint32_t availableCount = 0; @@ -174,7 +176,7 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe } if (result.frequency) - *result.frequency = properties.Frequency; + *result.frequency = properties.Frequency / 1000.; return NULL; } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 630f12ead1..c21465f0e0 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -255,8 +255,8 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->driverSpecific ? &gpu->type : NULL, - .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .type = &gpu->type, + .frequency = &gpu->frequency, }, "libnvidia-ml.so"); if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 1bbddd2c74..717d6389bb 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -100,7 +100,11 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount); if (result.frequency) - nvmlData.ffnvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency); + { + uint32_t clockMHz; + if (nvmlData.ffnvmlDeviceGetClockInfo(device, NVML_CLOCK_GRAPHICS, &clockMHz) == NVML_SUCCESS) + *result.frequency = clockMHz / 1000.; + } return NULL; } diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 3d27a7ba3d..fd0ba1046d 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -106,12 +106,13 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .subSystemId = subSystemId, .revId = revId, }, + .luid = gpu->deviceId, }, (FFGpuDriverResult) { .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->driverSpecific ? &gpu->type : NULL, - .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .type = &gpu->type, + .frequency = &gpu->frequency, }, gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? "nvml.dll" : #ifdef _WIN64 "ControlLib.dll" diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index 117eb2ceef..1fe09fb1a2 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -113,8 +113,8 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, - .type = options->driverSpecific ? &gpu->type : NULL, - .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .type = &gpu->type, + .frequency = &gpu->frequency, }, "/usr/lib/wsl/lib/libnvidia-ml.so"); } } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index a159764efa..a3360ad966 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -38,8 +38,8 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu if(gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) ffStrbufAppendF(&output, " (%d)", gpu->coreCount); - if(gpu->frequency != FF_GPU_FREQUENCY_UNSET) - ffStrbufAppendF(&output, " @ %.2f MHz", gpu->frequency / 1e6); + if(gpu->frequency == gpu->frequency && gpu->frequency > 0 /* Inactive? */) + ffStrbufAppendF(&output, " @ %.2f GHz", gpu->frequency); if(gpu->temperature == gpu->temperature) //FF_GPU_TEMP_UNSET { @@ -83,7 +83,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used}, - {FF_FORMAT_ARG_TYPE_UINT, &gpu->frequency}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->frequency}, }); } } @@ -312,7 +312,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) yyjson_mut_obj_add_null(doc, obj, "frequency"); else - yyjson_mut_obj_add_uint(doc, obj, "frequency", gpu->frequency); + yyjson_mut_obj_add_real(doc, obj, "frequency", gpu->frequency); } FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) From 1c5179d3b04358ece32da9a4b8b14aa27fd24b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 22:19:15 +0800 Subject: [PATCH 13/81] GPU (Intel): actually detect real time clock frequency --- src/detection/gpu/gpu_intel.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 4b67c6eb3e..b41d6e8aef 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -176,7 +176,25 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe } if (result.frequency) - *result.frequency = properties.Frequency / 1000.; + { + ctl_freq_handle_t freqs[16]; + uint32_t freqCount = sizeof(freqs) / sizeof(freqs[0]); + if (igclData.ffctlEnumFrequencyDomains(device, &freqCount, freqs) == CTL_RESULT_SUCCESS && freqCount > 0) + { + double sumValue = 0; + uint32_t availableCount = 0; + for (uint32_t iFreq = 0; iFreq < freqCount; iFreq++) + { + ctl_freq_state_t state = { .Size = sizeof(state), .Version = 0 }; + if (igclData.ffctlFrequencyGetState(freqs[iFreq], &state) == CTL_RESULT_SUCCESS) + { + sumValue += state.actual; + availableCount++; + } + } + *result.frequency = (sumValue / availableCount) / 1000.; + } + } return NULL; } From 72ed11ec9efd53c5bf1c680ace92460fe40f8543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 20 Dec 2023 22:23:02 +0800 Subject: [PATCH 14/81] 3rdparty: oops --- src/3rdparty/igcl/LICENSE | 27 +++++++++++++++++++++++++++ src/3rdparty/igcl/README.md | 15 --------------- src/3rdparty/igcl/repo.json | 2 +- 3 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 src/3rdparty/igcl/LICENSE delete mode 100644 src/3rdparty/igcl/README.md diff --git a/src/3rdparty/igcl/LICENSE b/src/3rdparty/igcl/LICENSE new file mode 100644 index 0000000000..852a8f259d --- /dev/null +++ b/src/3rdparty/igcl/LICENSE @@ -0,0 +1,27 @@ +Intel Software License Agreement +10.07.21 + +Use and Redistribution. You may use and redistribute Intel’s Control API software and the header files for the Intel® Graphics Control Library (collectively, the “Software”), solely for use on Intel platforms, provided the following conditions are met: +* Redistributions must reproduce the above copyright notice and the following terms of use in the Software and in the documentation and/or other materials provided with the distribution. +* Neither the name of Intel nor the names of its suppliers may be used to endorse or promote products derived from this Software without specific prior written permission. +* No reverse engineering, decompilation, or disassembly of Software provided to you in binary form is permitted. + +Third Party Software. The Software may contain Third Party Software. “Third Party Software” is third party software, open source software or other Intel software listed in the “third-party-software.txt” or other similarly named text file that is included with the Software. Third Party Software, even if included with the distribution of the Software, may be governed by separate license terms, including without limitation, third party license terms, open source software notices and terms, and/or other Intel software license terms. These separate license terms solely govern your use of the Third Party Software. + +Ownership. Title to the Software and all copies remain with Intel or its suppliers. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. THIS SOFTWARE IS NOT INTENDED FOR USE IN SYSTEMS OR APPLICATIONS WHERE FAILURE OF THE SOFTWARE MAY CAUSE PERSONAL INJURY OR DEATH AND YOU AGREE THAT YOU ARE FULLY RESPONSIBLE FOR ANY CLAIMS, COSTS, DAMAGES, EXPENSES, AND ATTORNEYS’ FEES ARISING OUT OF ANY SUCH USE, EVEN IF ANY CLAIM ALLEGES THAT INTEL WAS NEGLIGENT REGARDING THE DESIGN OR MANUFACTURE OF THE SOFTWARE. + +LIMITATION OF LIABILITY; INDEMNITY. IN NO EVENT WILL INTEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. YOU AGREE TO INDEMNIFY, DEFEND, AND HOLD INTEL HARMLESS AGAINST ANY CLAIMS, DAMAGES, AND EXPENSES RESULTING FROM YOUR USE OR UNAUTHORIZED USE OF THE SOFTWARE. + +No support. Intel may make changes to the Software, at any time without notice, and is not obligated to support, update or provide training for the Software. + +Termination. Your right to use the Software is terminated immediately in the event of your breach of this agreement. + +Feedback. Should you provide Intel with comments, modifications, corrections, enhancements or other input (“Feedback”) related to the Software Intel will be free to use, disclose, reproduce, license or otherwise distribute or exploit the Feedback in its sole discretion without any obligations or restrictions of any kind, including without limitation, intellectual property rights or licensing obligations. + +Compliance with laws. You agree to comply with all applicable laws and regulations governing your use, transfer, import or export (or prohibition thereof) of the Software. + +Governing law. All disputes will be governed by the laws of the United States of America and the State of Delaware without reference to conflict of law principles and subject to the exclusive jurisdiction of the state or federal courts sitting in the State of Delaware, and each party agrees that it submits to the personal jurisdiction and venue of those courts and waives any objections. The United Nations Convention on Contracts for the International Sale of Goods (1980) is specifically excluded and will not apply to the Software. + +Severability. The parties intend that if a court holds that any provision of this agreement is invalid or unenforceable under applicable law, the court will modify the provision to the minimum extent necessary to make it valid and enforceable or sever and delete the provision from this agreement. Any change to or deletion of a provision of this agreement under this Section will not affect the validity or enforceability of the remainder of this agreement, which will continue in full force and effect. diff --git a/src/3rdparty/igcl/README.md b/src/3rdparty/igcl/README.md deleted file mode 100644 index 12f3e4b90a..0000000000 --- a/src/3rdparty/igcl/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Intel Graphics Control Library (IGCL) -Header, wrapper library and samples of IGCL version 1.0 - - -# Introduction -IGCL is meant to be a collection of high level APIs for all control aspects of hardware, primarily graphics. This is replacement of legacy Intel CUISDK which used to be released only to OEM's and selected customers. IGCL allows global control and tweaking of display, media & 3D capabilities. - -# Notes -* IGCL binaries are distributed as part of Intel Graphics driver package. -* Header & library wrapper code are provided here to help developers with their application development. -* For API/spec questions or issues, for now, use the "Issues" tab under Github. For issues related to an already shipped binary of this spec, contact standard Intel customer support for Graphics. -* Performance & Telemetry API's, i.e., Engine/Fan/Telemetry/Frequency/Memory/Overclock/PCI/Power/Temperature are limited to 64-bit applications as of now. This is a Level0 limitation. - -# Usage -cmake.exe -B -S -G "Visual Studio 17 2022" -A x64 diff --git a/src/3rdparty/igcl/repo.json b/src/3rdparty/igcl/repo.json index 5c4bb82be9..b14aaacc0d 100644 --- a/src/3rdparty/igcl/repo.json +++ b/src/3rdparty/igcl/repo.json @@ -1,6 +1,6 @@ { "home": "https://github.com/intel/drivers.gpu.control-library", - "license": "README.md", + "license": "./LICENSE", "version": "e1776b7be2ceead1296204371447b27860d25a66", "author": "Intel Corporation" } From a1d81b4964a59f311eda9fbed181971a7898f0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Dec 2023 09:52:15 +0800 Subject: [PATCH 15/81] fastfetch: fix compiler warnings --- src/fastfetch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastfetch.c b/src/fastfetch.c index f37d14bd53..f60ae9ad35 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -267,7 +267,7 @@ static void listConfigPaths(void) FF_LIST_FOR_EACH(FFstrbuf, folder, instance.state.platform.configDirs) { bool exists = false; - uint32_t length = folder->length + sizeof("fastfetch"); + uint32_t length = folder->length + (uint32_t) strlen("fastfetch") + 1 /* trailing slash */; ffStrbufAppendS(folder, "fastfetch/config.jsonc"); exists = ffPathExists(folder->chars, FF_PATHTYPE_FILE); if (!exists) From c5695542b2877fa4cc0fb214116480c7aeb6cfbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Dec 2023 09:23:21 +0800 Subject: [PATCH 16/81] CI: generate sha256sum for source tarballs Ref: https://github.com/ncipollo/release-action/issues/400 --- .github/workflows/ci.yml | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 938bc5058e..cdbf5e67dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -369,29 +369,45 @@ jobs: permissions: contents: write steps: - - name: download artifacts - uses: actions/download-artifact@v4 - - name: get latest release version id: get_version_release uses: pozetroninc/github-action-get-latest-release@master with: repository: ${{ github.repository }} - - name: generate release-notes + - name: download artifacts + if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release + uses: actions/download-artifact@v4 + + - name: create release + if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release + uses: ncipollo/release-action@v1 + with: + tag: ${{ needs.linux.outputs.ffversion }} + commit: ${{ github.sha }} + artifactErrorsFailBuild: true + artifacts: fastfetch-*/fastfetch-* + body: "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." + + - name: download source tarballs + if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release run: | + for i in 1 2 3 4 5; do curl -L --remote-name-all --output-dir fastfetch-source --create-dirs https://github.com/${{ github.repository }}/archive/refs/tags/${{ needs.linux.outputs.ffversion }}.{tar.gz,zip} && break || sleep 5; done ls fastfetch-*/* - echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md#${{ needs.linux.outputs.ffversion }}) for details." > fastfetch-release-notes.md + + - name: generate release notes + if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release + run: | + echo "Please refer to [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/${{ needs.linux.outputs.ffversion }}/CHANGELOG.md) for details." > fastfetch-release-notes.md echo -e "\n---\n\n
SHA256SUMs
\n\n\`\`\`" >> fastfetch-release-notes.md sha256sum fastfetch-*/* >> fastfetch-release-notes.md - echo -e "\n\`\`\`\n
" >> fastfetch-release-notes.md + echo -e "\`\`\`\n" >> fastfetch-release-notes.md - - name: create release + - name: update release body if: needs.linux.outputs.ffversion != steps.get_version_release.outputs.release uses: ncipollo/release-action@v1 with: tag: ${{ needs.linux.outputs.ffversion }} commit: ${{ github.sha }} bodyFile: fastfetch-release-notes.md - artifactErrorsFailBuild: true - artifacts: fastfetch-*/* + allowUpdates: true From dfb0eecf86175051a1cdfcf18906311d261bd2b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Dec 2023 14:53:35 +0800 Subject: [PATCH 17/81] 3rdparty: add amd_ags --- CMakeLists.txt | 1 + src/3rdparty/ags/amd_ags.h | 1355 +++++++++++++++++++++++ src/3rdparty/ags/repo.json | 6 + src/detection/gpu/gpu_amd.c | 67 ++ src/detection/gpu/gpu_driver_specific.h | 1 + src/detection/gpu/gpu_windows.c | 62 +- 6 files changed, 1478 insertions(+), 14 deletions(-) create mode 100644 src/3rdparty/ags/amd_ags.h create mode 100644 src/3rdparty/ags/repo.json create mode 100644 src/detection/gpu/gpu_amd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f0c8c3779c..3a10d9449a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,6 +631,7 @@ elseif(WIN32) src/detection/gpu/gpu_windows.c src/detection/gpu/gpu_nvidia.c src/detection/gpu/gpu_intel.c + src/detection/gpu/gpu_amd.c src/detection/host/host_windows.c src/detection/icons/icons_windows.c src/detection/libc/libc_windows.cpp diff --git a/src/3rdparty/ags/amd_ags.h b/src/3rdparty/ags/amd_ags.h new file mode 100644 index 0000000000..7d23863a40 --- /dev/null +++ b/src/3rdparty/ags/amd_ags.h @@ -0,0 +1,1355 @@ +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +/// \file +/// \mainpage +/// AGS Library Overview +/// -------------------- +/// This document provides an overview of the AGS (AMD GPU Services) library. The AGS library provides software developers with the ability to query +/// AMD GPU software and hardware state information that is not normally available through standard operating systems or graphic APIs. +/// +/// The latest version of the API is publicly hosted here: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/. +/// It is also worth checking http://gpuopen.com/gaming-product/amd-gpu-services-ags-library/ for any updates and articles on AGS. +/// \internal +/// Online documentation is publicly hosted here: http://gpuopen-librariesandsdks.github.io/ags/ +/// \endinternal +/// +/// --------------------------------------- +/// What's new in AGS 6.2 since version 6.1 +/// --------------------------------------- +/// AGS 6.2 includes the following updates: +/// * Shader clock intrinsics +/// * Minor improvements and fixes +/// +/// --------------------------------------- +/// What's new in AGS 6.1 since version 6.0 +/// --------------------------------------- +/// AGS 6.1 includes the following updates: +/// * RDNA3 detection +/// +/// --------------------------------------- +/// What's new in AGS 6.0 since version 5.4.2 +/// --------------------------------------- +/// AGS 6.0 includes the following updates: +/// * DX12 ray tracing hit token for RDNA2 hardware. +/// * Shader intrinsic that exposes ReadLaneAt in DX12. +/// * Shader intrinsics that expose explicit float conversions in DX12. +/// * Refactored and revised API to minimize user error. +/// * Added agsGetVersionNumber. +/// * Detection for external GPUs. +/// * Detection of RDNA2 architecture. +/// * Grouped the more established intrinsics together into per year support. +/// * Function pointer typedefs for the API +/// +/// --------------------------------------- +/// What's new in AGS 5.4.2 since version 5.4.1 +/// --------------------------------------- +/// AGS 5.4.2 includes the following updates: +/// * sharedMemoryInBytes has been reinstated. +/// * Clock speed returned for APUs. +/// +/// --------------------------------------- +/// What's new in AGS 5.4.1 since version 5.4.0 +/// --------------------------------------- +/// AGS 5.4.1 includes the following updates: +/// * AsicFamily_Count to help with code maintenance. +/// * Visual Studio 2019 support. +/// * x86 support +/// * BaseInstance and BaseVertex intrinsics along with corresponding caps bits. +/// * GetWaveSize intrinsic along with corresponding caps bits. +/// +/// --------------------------------------- +/// What's new in AGS 5.4 since version 5.3 +/// --------------------------------------- +/// AGS 5.4 includes the following updates: +/// * A more detailed description of the GPU architecture, now including RDNA GPUs. +/// * Radeon 7 core and memory speeds returned. +/// * Draw index and Atomic U64 intrinsics for both DX11 and DX12. +/// +/// --------------------------------------- +/// What's new in AGS 5.3 since version 5.2 +/// --------------------------------------- +/// AGS 5.3 includes the following updates: +/// * DX11 deferred context support for Multi Draw Indirect and UAV Overlap extensions. +/// * A Radeon Software Version helper to determine whether the installed driver meets your game's minimum driver version requirements. +/// * Freesync HDR Gamma 2.2 mode which uses a 1010102 swapchain and can be considered as an alternative to using the 64 bit swapchain required for Freesync HDR scRGB. +/// +/// Using the AGS library +/// --------------------- +/// It is recommended to take a look at the source code for the samples that come with the AGS SDK: +/// * AGSSample +/// * CrossfireSample +/// * EyefinitySample +/// The AGSSample application is the simplest of the three examples and demonstrates the code required to initialize AGS and use it to query the GPU and Eyefinity state. +/// The CrossfireSample application demonstrates the use of the new API to transfer resources on GPUs in Crossfire mode. Lastly, the EyefinitySample application provides a more +/// extensive example of Eyefinity setup than the basic example provided in AGSSample. +/// There are other samples on Github that demonstrate the DirectX shader extensions, such as the Barycentrics11 and Barycentrics12 samples. +/// +/// To add AGS support to an existing project, follow these steps: +/// * Link your project against the correct import library. Choose from either the 32 bit or 64 bit version. +/// * Copy the AGS dll into the same directory as your game executable. +/// * Include the amd_ags.h header file from your source code. +/// * Include the AGS hlsl files if you are using the shader intrinsics. +/// * Declare a pointer to an AGSContext and make this available for all subsequent calls to AGS. +/// * On game initialization, call \ref agsInitialize passing in the address of the context. On success, this function will return a valid context pointer. +/// +/// Don't forget to cleanup AGS by calling \ref agsDeInitialize when the app exits, after the device has been destroyed. + +#ifndef AMD_AGS_H +#define AMD_AGS_H + +#define AMD_AGS_VERSION_MAJOR 6 ///< AGS major version +#define AMD_AGS_VERSION_MINOR 2 ///< AGS minor version +#define AMD_AGS_VERSION_PATCH 0 ///< AGS patch version + +#ifdef __cplusplus +extern "C" { +#endif + +/// \defgroup Defines AGS defines +/// @{ +#if defined (AGS_GCC) +#define AMD_AGS_API +#else +#define AMD_AGS_API __declspec(dllexport) ///< AGS exported functions +#endif + +#define AGS_MAKE_VERSION( major, minor, patch ) ( ( major << 22 ) | ( minor << 12 ) | patch ) ///< Macro to create the app and engine versions for the fields in \ref AGSDX12ExtensionParams and \ref AGSDX11ExtensionParams and the Radeon Software Version +#define AGS_UNSPECIFIED_VERSION 0xFFFFAD00 ///< Use this to specify no version +#define AGS_CURRENT_VERSION AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ) ///< Macro to return the current AGS version as defined by the AGS header file +/// @} + +#if !defined (AGS_DIRECTX_TYPES_INCLUDED) +// Forward declaration of D3D and DXGI types +struct IDXGIAdapter; +struct IDXGISwapChain; +struct DXGI_SWAP_CHAIN_DESC; +enum D3D_DRIVER_TYPE; +enum D3D_FEATURE_LEVEL; +enum D3D_PRIMITIVE_TOPOLOGY; + +// Forward declaration of D3D11 types +struct ID3D11Device; +struct ID3D11DeviceContext; +struct ID3D11Resource; +struct ID3D11Buffer; +struct ID3D11Texture1D; +struct ID3D11Texture2D; +struct ID3D11Texture3D; +struct D3D11_BUFFER_DESC; +struct D3D11_TEXTURE1D_DESC; +struct D3D11_TEXTURE2D_DESC; +struct D3D11_TEXTURE3D_DESC; +struct D3D11_SUBRESOURCE_DATA; +struct tagRECT; +typedef tagRECT D3D11_RECT; ///< typedef this ourselves so we don't have to drag d3d11.h in + +// Forward declaration of D3D12 types +struct ID3D12Device; +struct ID3D12GraphicsCommandList; +#endif + +/// \defgroup enums General enumerations +/// @{ + +/// The return codes +typedef enum AGSReturnCode +{ + AGS_SUCCESS, ///< Successful function call + AGS_FAILURE, ///< Failed to complete call for some unspecified reason + AGS_INVALID_ARGS, ///< Invalid arguments into the function + AGS_OUT_OF_MEMORY, ///< Out of memory when allocating space internally + AGS_MISSING_D3D_DLL, ///< Returned when a D3D dll fails to load + AGS_LEGACY_DRIVER, ///< Returned if a feature is not present in the installed driver + AGS_NO_AMD_DRIVER_INSTALLED, ///< Returned if the AMD GPU driver does not appear to be installed + AGS_EXTENSION_NOT_SUPPORTED, ///< Returned if the driver does not support the requested driver extension + AGS_ADL_FAILURE, ///< Failure in ADL (the AMD Display Library) + AGS_DX_FAILURE, ///< Failure from DirectX runtime + AGS_D3DDEVICE_NOT_CREATED ///< Failure due to not creating the D3D device successfully via AGS. +} AGSReturnCode; + +/// @} + +struct AGSContext; ///< All function calls in AGS require a pointer to a context. This is generated via \ref agsInitialize + +/// The rectangle struct used by AGS. +typedef struct AGSRect +{ + int offsetX; ///< Offset on X axis + int offsetY; ///< Offset on Y axis + int width; ///< Width of rectangle + int height; ///< Height of rectangle +} AGSRect; + +/// The display info struct used to describe a display enumerated by AGS +typedef struct AGSDisplayInfo +{ + char name[ 256 ]; ///< The name of the display + char displayDeviceName[ 32 ]; ///< The display device name, i.e. DISPLAY_DEVICE::DeviceName + + unsigned int isPrimaryDisplay : 1; ///< Whether this display is marked as the primary display + unsigned int HDR10 : 1; ///< HDR10 is supported on this display + unsigned int dolbyVision : 1; ///< Dolby Vision is supported on this display + unsigned int freesync : 1; ///< Freesync is supported on this display + unsigned int freesyncHDR : 1; ///< Freesync HDR is supported on this display + unsigned int eyefinityInGroup : 1; ///< The display is part of the Eyefinity group + unsigned int eyefinityPreferredDisplay : 1; ///< The display is the preferred display in the Eyefinity group for displaying the UI + unsigned int eyefinityInPortraitMode : 1; ///< The display is in the Eyefinity group but in portrait mode + unsigned int reservedPadding : 24; ///< Reserved for future use + + int maxResolutionX; ///< The maximum supported resolution of the unrotated display + int maxResolutionY; ///< The maximum supported resolution of the unrotated display + float maxRefreshRate; ///< The maximum supported refresh rate of the display + + AGSRect currentResolution; ///< The current resolution and position in the desktop, ignoring Eyefinity bezel compensation + AGSRect visibleResolution; ///< The visible resolution and position. When Eyefinity bezel compensation is enabled this will + ///< be the sub region in the Eyefinity single large surface (SLS) + float currentRefreshRate; ///< The current refresh rate + + int eyefinityGridCoordX; ///< The X coordinate in the Eyefinity grid. -1 if not in an Eyefinity group + int eyefinityGridCoordY; ///< The Y coordinate in the Eyefinity grid. -1 if not in an Eyefinity group + + double chromaticityRedX; ///< Red display primary X coord + double chromaticityRedY; ///< Red display primary Y coord + + double chromaticityGreenX; ///< Green display primary X coord + double chromaticityGreenY; ///< Green display primary Y coord + + double chromaticityBlueX; ///< Blue display primary X coord + double chromaticityBlueY; ///< Blue display primary Y coord + + double chromaticityWhitePointX; ///< White point X coord + double chromaticityWhitePointY; ///< White point Y coord + + double screenDiffuseReflectance; ///< Percentage expressed between 0 - 1 + double screenSpecularReflectance; ///< Percentage expressed between 0 - 1 + + double minLuminance; ///< The minimum luminance of the display in nits + double maxLuminance; ///< The maximum luminance of the display in nits + double avgLuminance; ///< The average luminance of the display in nits + + int logicalDisplayIndex; ///< The internally used index of this display + int adlAdapterIndex; ///< The internally used ADL adapter index + int reserved; ///< reserved field +} AGSDisplayInfo; + +/// The device info struct used to describe a physical GPU enumerated by AGS +typedef struct AGSDeviceInfo +{ + /// The ASIC family + typedef enum AsicFamily + { + AsicFamily_Unknown, ///< Unknown architecture, potentially from another IHV. Check \ref AGSDeviceInfo::vendorId + AsicFamily_PreGCN, ///< Pre GCN architecture. + AsicFamily_GCN1, ///< AMD GCN 1 architecture: Oland, Cape Verde, Pitcairn & Tahiti. + AsicFamily_GCN2, ///< AMD GCN 2 architecture: Hawaii & Bonaire. This also includes APUs Kaveri and Carrizo. + AsicFamily_GCN3, ///< AMD GCN 3 architecture: Tonga & Fiji. + AsicFamily_GCN4, ///< AMD GCN 4 architecture: Polaris. + AsicFamily_Vega, ///< AMD Vega architecture, including Raven Ridge (ie AMD Ryzen CPU + AMD Vega GPU). + AsicFamily_RDNA, ///< AMD RDNA architecture + AsicFamily_RDNA2, ///< AMD RDNA2 architecture + AsicFamily_RDNA3, ///< AMD RDNA3 architecture + + AsicFamily_Count ///< Number of enumerated ASIC families + } AsicFamily; + + const char* adapterString; ///< The adapter name string + AsicFamily asicFamily; ///< Set to Unknown if not AMD hardware + unsigned int isAPU : 1; ///< Whether this device is an APU + unsigned int isPrimaryDevice : 1; ///< Whether this device is marked as the primary device + unsigned int isExternal :1; ///< Whether this device is a detachable, external device + unsigned int reservedPadding : 29; ///< Reserved for future use + + int vendorId; ///< The vendor id + int deviceId; ///< The device id + int revisionId; ///< The revision id + + int numCUs; ///< Number of compute units + int numWGPs; ///< Number of RDNA Work Group Processors. Only valid if ASIC is RDNA onwards. + + int numROPs; ///< Number of ROPs + int coreClock; ///< Core clock speed at 100% power in MHz + int memoryClock; ///< Memory clock speed at 100% power in MHz + int memoryBandwidth; ///< Memory bandwidth in MB/s + float teraFlops; ///< Teraflops of GPU. Zero if not GCN onwards. Calculated from iCoreClock * iNumCUs * 64 Pixels/clk * 2 instructions/MAD + + unsigned long long localMemoryInBytes; ///< The size of local memory in bytes. 0 for non AMD hardware. + unsigned long long sharedMemoryInBytes; ///< The size of system memory available to the GPU in bytes. It is important to factor this into your VRAM budget for APUs + ///< as the reported local memory will only be a small fraction of the total memory available to the GPU. + + int numDisplays; ///< The number of active displays found to be attached to this adapter. + AGSDisplayInfo* displays; ///< List of displays allocated by AGS to be numDisplays in length. + + int eyefinityEnabled; ///< Indicates if Eyefinity is active + int eyefinityGridWidth; ///< Contains width of the multi-monitor grid that makes up the Eyefinity Single Large Surface. + int eyefinityGridHeight; ///< Contains height of the multi-monitor grid that makes up the Eyefinity Single Large Surface. + int eyefinityResolutionX; ///< Contains width in pixels of the multi-monitor Single Large Surface. + int eyefinityResolutionY; ///< Contains height in pixels of the multi-monitor Single Large Surface. + int eyefinityBezelCompensated; ///< Indicates if bezel compensation is used for the current SLS display area. 1 if enabled, and 0 if disabled. + + int adlAdapterIndex; ///< Internally used index into the ADL list of adapters + int reserved; ///< reserved field +} AGSDeviceInfo; + +/// \defgroup general General API functions +/// API for initialization, cleanup, HDR display modes and Crossfire GPU count +/// @{ + +typedef void* (__stdcall *AGS_ALLOC_CALLBACK)( size_t allocationSize ); ///< AGS user defined allocation prototype +typedef void (__stdcall *AGS_FREE_CALLBACK)( void* allocationPtr ); ///< AGS user defined free prototype + +/// The configuration options that can be passed in to \ref agsInitialize +typedef struct AGSConfiguration +{ + AGS_ALLOC_CALLBACK allocCallback; ///< Optional memory allocation callback. If not supplied, malloc() is used + AGS_FREE_CALLBACK freeCallback; ///< Optional memory freeing callback. If not supplied, free() is used +} AGSConfiguration; + +/// The top level GPU information returned from \ref agsInitialize +typedef struct AGSGPUInfo +{ + const char* driverVersion; ///< The AMD driver package version + const char* radeonSoftwareVersion; ///< The Radeon Software Version + + int numDevices; ///< Number of GPUs in the system + AGSDeviceInfo* devices; ///< List of GPUs in the system +} AGSGPUInfo; + +/// The struct to specify the display settings to the driver. +typedef struct AGSDisplaySettings +{ + /// The display mode + typedef enum Mode + { + Mode_SDR, ///< SDR mode + Mode_HDR10_PQ, ///< HDR10 PQ encoding, requiring a 1010102 UNORM swapchain and PQ encoding in the output shader. + Mode_HDR10_scRGB, ///< HDR10 scRGB, requiring an FP16 swapchain. Values of 1.0 == 80 nits, 125.0 == 10000 nits. + Mode_FreesyncHDR_scRGB, ///< Freesync HDR scRGB, requiring an FP16 swapchain. A value of 1.0 == 80 nits. + Mode_FreesyncHDR_Gamma22, ///< Freesync HDR Gamma 2.2, requiring a 1010102 UNORM swapchain. The output needs to be encoded to gamma 2.2. + Mode_DolbyVision, ///< Dolby Vision, requiring an 8888 UNORM swapchain + + Mode_Count ///< Number of enumerated display modes + } Mode; + + Mode mode; ///< The display mode to set the display into + + double chromaticityRedX; ///< Red display primary X coord + double chromaticityRedY; ///< Red display primary Y coord + + double chromaticityGreenX; ///< Green display primary X coord + double chromaticityGreenY; ///< Green display primary Y coord + + double chromaticityBlueX; ///< Blue display primary X coord + double chromaticityBlueY; ///< Blue display primary Y coord + + double chromaticityWhitePointX; ///< White point X coord + double chromaticityWhitePointY; ///< White point Y coord + + double minLuminance; ///< The minimum scene luminance in nits + double maxLuminance; ///< The maximum scene luminance in nits + + double maxContentLightLevel; ///< The maximum content light level in nits (MaxCLL) + double maxFrameAverageLightLevel; ///< The maximum frame average light level in nits (MaxFALL) + + unsigned int disableLocalDimming : 1; ///< Disables local dimming if possible + unsigned int reservedPadding : 31; ///< Reserved +} AGSDisplaySettings; + + +/// The result returned from \ref agsCheckDriverVersion +typedef enum AGSDriverVersionResult +{ + AGS_SOFTWAREVERSIONCHECK_OK, ///< The reported Radeon Software Version is newer or the same as the required version + AGS_SOFTWAREVERSIONCHECK_OLDER, ///< The reported Radeon Software Version is older than the required version + AGS_SOFTWAREVERSIONCHECK_UNDEFINED ///< The check could not determine as result. This could be because it is a private or custom driver or just invalid arguments. +} AGSDriverVersionResult; + +/// +/// Helper function to check the installed software version against the required software version. +/// +/// \param [in] radeonSoftwareVersionReported The Radeon Software Version returned from \ref AGSGPUInfo::radeonSoftwareVersion. +/// \param [in] radeonSoftwareVersionRequired The Radeon Software Version to check against. This is specificed using \ref AGS_MAKE_VERSION. +/// \return The result of the check. +/// +AMD_AGS_API AGSDriverVersionResult agsCheckDriverVersion( const char* radeonSoftwareVersionReported, unsigned int radeonSoftwareVersionRequired ); + +/// +/// Function to return the AGS version number. +/// +/// \return The version number made using AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ). +/// +AMD_AGS_API int agsGetVersionNumber(); + +/// +/// Function used to initialize the AGS library. +/// agsVersion must be specified as AGS_CURRENT_VERSION or the call will return \ref AGS_INVALID_ARGS. +/// Must be called prior to any of the subsequent AGS API calls. +/// Must be called prior to ID3D11Device or ID3D12Device creation. +/// \note The caller of this function should handle the possibility of the call failing in the cases below. One option is to do a vendor id check and only call \ref agsInitialize if there is an AMD GPU present. +/// \note This function will fail with \ref AGS_NO_AMD_DRIVER_INSTALLED if there is no AMD driver found on the system. +/// \note This function will fail with \ref AGS_LEGACY_DRIVER in Catalyst versions before 12.20. +/// +/// \param [in] agsVersion The API version specified using the \ref AGS_CURRENT_VERSION macro. If this does not match the version in the binary this initialization call will fail. +/// \param [in] config Optional pointer to a AGSConfiguration struct to override the default library configuration. +/// \param [out] context Address of a pointer to a context. This function allocates a context on the heap which is then required for all subsequent API calls. +/// \param [out] gpuInfo Optional pointer to a AGSGPUInfo struct which will get filled in for all the GPUs in the system. +/// +AMD_AGS_API AGSReturnCode agsInitialize( int agsVersion, const AGSConfiguration* config, AGSContext** context, AGSGPUInfo* gpuInfo ); + +/// +/// Function used to clean up the AGS library. +/// +/// \param [in] context Pointer to a context. This function will deallocate the context from the heap. +/// +AMD_AGS_API AGSReturnCode agsDeInitialize( AGSContext* context ); + +/// +/// Function used to set a specific display into HDR mode +/// \note Setting all of the values apart from color space and transfer function to zero will cause the display to use defaults. +/// \note Call this function after each mode change (switch to fullscreen, any change in swapchain etc). +/// \note HDR10 PQ mode requires a 1010102 swapchain. +/// \note HDR10 scRGB mode requires an FP16 swapchain. +/// \note Freesync HDR scRGB mode requires an FP16 swapchain. +/// \note Freesync HDR Gamma 2.2 mode requires a 1010102 swapchain. +/// \note Dolby Vision requires a 8888 UNORM swapchain. +/// +/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize +/// \param [in] deviceIndex The index of the device listed in \ref AGSGPUInfo::devices. +/// \param [in] displayIndex The index of the display listed in \ref AGSDeviceInfo::displays. +/// \param [in] settings Pointer to the display settings to use. +/// +AMD_AGS_API AGSReturnCode agsSetDisplayMode( AGSContext* context, int deviceIndex, int displayIndex, const AGSDisplaySettings* settings ); + +/// @} + +/// @} + + +/// \defgroup dxappreg App Registration +/// @{ +/// This extension allows an application to voluntarily register itself with the driver, providing a more robust app detection solution and avoid the issue of the driver relying on exe names to match the app to a driver profile. +/// It is available when creating the device for both DirectX11 and DirectX12 via \ref agsDriverExtensionsDX11_CreateDevice and \ref agsDriverExtensionsDX12_CreateDevice respectively. +/// This feature is supported in Radeon Software Version 17.9.2 onwards. +/// Rules: +/// * AppName or EngineName must be set, but both are not required. Engine profiles will be used only if app specific profiles do not exist. +/// * In an engine, the EngineName should be set, so a default profile can be built. If an app modifies the engine, the AppName should be set, to allow a profile for the specific app. +/// * Version number is not mandatory, but recommended. The use of which can prevent the use of profiles for incompatible versions (for instance engine versions that introduce or change features), and can help prevent older profiles from being used (and introducing new bugs) before the profile is tested with new app builds. +/// * If Version numbers are used and a new version is introduced, a new profile will not be enabled until an AMD engineer has been able to update a previous profile, or make a new one. +/// +/// The cases for profile selection are as follows: +/// +/// |Case|Profile Applied| +/// |----|---------------| +/// | App or Engine Version has profile | The profile is used. | +/// | App or Engine Version num < profile version num | The closest profile > the version number is used. | +/// | App or Engine Version num > profile version num | No profile selected/The previous method is used. | +/// | App and Engine Version have profile | The App's profile is used. | +/// | App and Engine Version num < profile version | The closest App profile > the version number is used. | +/// | App and Engine Version, no App profile found | The Engine profile will be used. | +/// | App/Engine name but no Version, has profile | The latest profile is used. | +/// | No name or version, or no profile | The previous app detection method is used. | +/// +/// As shown above, if an App name is given, and a profile is found for that app, that will be prioritized. The Engine name and profile will be used only if no app name is given, or no viable profile is found for the app name. +/// In the case that App nor Engine have a profile, the previous app detection methods will be used. If given a version number that is larger than any profile version number, no profile will be selected. +/// This is specifically to prevent cases where an update to an engine or app will cause catastrophic breaks in the profile, allowing an engineer to test the profile before clearing it for public use with the new engine/app update. +/// +/// @} + +/// \defgroup dx12 DirectX12 Extensions +/// DirectX12 driver extensions +/// @{ + +/// \defgroup dx12init Device and device object creation and cleanup +/// It is now mandatory to call \ref agsDriverExtensionsDX12_CreateDevice when creating a device if the user wants to access any future DX12 AMD extensions. +/// The corresponding \ref agsDriverExtensionsDX12_DestroyDevice call must be called to release the device and free up the internal resources allocated by the create call. +/// @{ + +/// The struct to specify the DX12 device creation parameters +typedef struct AGSDX12DeviceCreationParams +{ + IDXGIAdapter* pAdapter; ///< Pointer to the adapter to use when creating the device. This may be null. + IID iid; ///< The interface ID for the type of device to be created. + D3D_FEATURE_LEVEL FeatureLevel; ///< The minimum feature level to create the device with. +} AGSDX12DeviceCreationParams; + +/// The struct to specify DX12 additional device creation parameters +typedef struct AGSDX12ExtensionParams +{ + const WCHAR* pAppName; ///< Application name + const WCHAR* pEngineName; ///< Engine name + unsigned int appVersion; ///< Application version + unsigned int engineVersion; ///< Engine version + unsigned int uavSlot; ///< The UAV slot reserved for intrinsic support. Refer to the \ref agsDriverExtensionsDX12_CreateDevice documentation for more details. +} AGSDX12ExtensionParams; + +/// The struct to hold all the returned parameters from the device creation call +typedef struct AGSDX12ReturnedParams +{ + ID3D12Device* pDevice; ///< The newly created device + typedef struct ExtensionsSupported /// Extensions for DX12 + { + unsigned int intrinsics16 : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. ReadFirstLane, ReadLane, LaneID, Swizzle, Ballot, MBCount, Med3, Barycentrics + unsigned int intrinsics17 : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. WaveReduce, WaveScan + unsigned int userMarkers : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. + unsigned int appRegistration : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. + unsigned int UAVBindSlot : 1; ///< Supported in Radeon Software Version 19.5.1 onwards. + unsigned int intrinsics19 : 1; ///< Supported in Radeon Software Version 19.12.2 onwards. DrawIndex, AtomicU64 + unsigned int baseVertex : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. + unsigned int baseInstance : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. + unsigned int getWaveSize : 1; ///< Supported in Radeon Software Version 20.5.1 onwards. + unsigned int floatConversion : 1; ///< Supported in Radeon Software Version 20.5.1 onwards. + unsigned int readLaneAt : 1; ///< Supported in Radeon Software Version 20.11.2 onwards. + unsigned int rayHitToken : 1; ///< Supported in Radeon Software Version 20.11.2 onwards. + unsigned int shaderClock : 1; ///< Supported in Radeon Software Version 23.1.1 onwards. + unsigned int padding : 19; ///< Reserved + } ExtensionsSupported; + ExtensionsSupported extensionsSupported; ///< List of supported extensions +} AGSDX12ReturnedParams; + +/// The space id for DirectX12 intrinsic support +const unsigned int AGS_DX12_SHADER_INTRINSICS_SPACE_ID = 0x7FFF0ADE; // 2147420894 + +/// +/// Function used to create a D3D12 device with additional AMD-specific initialization parameters. +/// +/// When using the HLSL shader extensions please note: +/// * The shader compiler should not use the D3DCOMPILE_SKIP_OPTIMIZATION (/Od) option or /O0, otherwise it will not work. +/// * The shader compiler needs D3DCOMPILE_ENABLE_STRICTNESS (/Ges) enabled. +/// * The intrinsic instructions require a 5.1 shader model. +/// * The Root Signature will need to reserve an extra UAV resource slot. This is not a real resource that requires allocating, it is just used to encode the intrinsic instructions. +/// +/// The easiest way to set up the reserved UAV slot is to specify it at u0. The register space id will automatically be assumed to be \ref AGS_DX12_SHADER_INTRINSICS_SPACE_ID. +/// The HLSL expects this as default and the set up code would look similar to this: +/// \code{.cpp} +/// CD3DX12_DESCRIPTOR_RANGE range[]; +/// ... +/// range[ 0 ].Init( D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, AGS_DX12_SHADER_INTRINSICS_SPACE_ID ); // u0 at driver-reserved space id +/// \endcode +/// +/// Newer drivers also support a user-specified slot in which case the register space id is assumed to be 0. It is important that the \ref AGSDX12ReturnedParams::ExtensionsSupported::UAVBindSlot bit is set. +/// to ensure the driver can support this. If not, then u0 and \ref AGS_DX12_SHADER_INTRINSICS_SPACE_ID must be used. +/// If the driver does support this feature and a non zero slot is required, then the HLSL must also define AMD_EXT_SHADER_INTRINSIC_UAV_OVERRIDE as the matching slot value. +/// +/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize +/// \param [in] creationParams Pointer to the struct to specify the existing DX12 device creation parameters. +/// \param [in] extensionParams Optional pointer to the struct to specify DX12 additional device creation parameters. +/// \param [out] returnedParams Pointer to struct to hold all the returned parameters from the call. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_CreateDevice( AGSContext* context, const AGSDX12DeviceCreationParams* creationParams, const AGSDX12ExtensionParams* extensionParams, AGSDX12ReturnedParams* returnedParams ); + +/// +/// Function to destroy the D3D12 device. +/// This call will also cleanup any AMD-specific driver extensions for D3D12. +/// +/// \param [in] context Pointer to a context. +/// \param [in] device Pointer to the D3D12 device. +/// \param [out] deviceReferences Optional pointer to an unsigned int that will be set to the value returned from device->Release(). +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_DestroyDevice( AGSContext* context, ID3D12Device* device, unsigned int* deviceReferences ); + +/// @} + +/// \defgroup dx12usermarkers User Markers +/// @{ + +/// +/// Function used to push an AMD user marker onto the command list. +/// This is only has an effect if \ref AGSDX12ReturnedParams::ExtensionsSupported::userMarkers is present. +/// Supported in Radeon Software Version 17.9.1 onwards. +/// +/// \param [in] context Pointer to a context. +/// \param [in] commandList Pointer to the command list. +/// \param [in] data The UTF-8 marker string. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_PushMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList, const char* data ); + +/// +/// Function used to pop an AMD user marker on the command list. +/// Supported in Radeon Software Version 17.9.1 onwards. +/// +/// \param [in] context Pointer to a context. +/// \param [in] commandList Pointer to the command list. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_PopMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList ); + +/// +/// Function used to insert an single event AMD user marker onto the command list. +/// Supported in Radeon Software Version 17.9.1 onwards. +/// +/// \param [in] context Pointer to a context. +/// \param [in] commandList Pointer to the command list. +/// \param [in] data The UTF-8 marker string. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_SetMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList, const char* data ); + +/// @} + +/// @} + +/// \defgroup dx11 DirectX11 Extensions +/// DirectX11 driver extensions +/// @{ + +/// \defgroup dx11init Device creation and cleanup +/// It is now mandatory to call \ref agsDriverExtensionsDX11_CreateDevice when creating a device if the user wants to access any DX11 AMD extensions. +/// The corresponding \ref agsDriverExtensionsDX11_DestroyDevice call must be called to release the device and free up the internal resources allocated by the create call. +/// @{ + +/// The different modes to control Crossfire behavior. +typedef enum AGSCrossfireMode +{ + AGS_CROSSFIRE_MODE_DRIVER_AFR = 0, ///< Use the default driver-based AFR rendering. If this mode is specified, do NOT use the agsDriverExtensionsDX11_Create*() APIs to create resources + AGS_CROSSFIRE_MODE_EXPLICIT_AFR, ///< Use the AGS Crossfire API functions to perform explicit AFR rendering without requiring a CF driver profile + AGS_CROSSFIRE_MODE_DISABLE ///< Completely disable AFR rendering +} AGSCrossfireMode; + +/// The struct to specify the existing DX11 device creation parameters +typedef struct AGSDX11DeviceCreationParams +{ + IDXGIAdapter* pAdapter; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + D3D_DRIVER_TYPE DriverType; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + HMODULE Software; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + UINT Flags; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + const D3D_FEATURE_LEVEL* pFeatureLevels; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + UINT FeatureLevels; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + UINT SDKVersion; ///< Consult the DX documentation on D3D11CreateDevice for this parameter + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc; ///< Optional swapchain description. Specify this to invoke D3D11CreateDeviceAndSwapChain instead of D3D11CreateDevice. +} AGSDX11DeviceCreationParams; + +/// The struct to specify DX11 additional device creation parameters +typedef struct AGSDX11ExtensionParams +{ + const WCHAR* pAppName; ///< Application name + const WCHAR* pEngineName; ///< Engine name + unsigned int appVersion; ///< Application version + unsigned int engineVersion; ///< Engine version + unsigned int numBreadcrumbMarkers; ///< The number of breadcrumb markers to allocate. Each marker is a uint64 (ie 8 bytes). If 0, the system is disabled. + unsigned int uavSlot; ///< The UAV slot reserved for intrinsic support. This must match the slot defined in the HLSL, i.e. "#define AmdDxExtShaderIntrinsicsUAVSlot". + /// The default slot is 7, but the caller is free to use an alternative slot. + /// If 0 is specified, then the default of 7 will be used. + AGSCrossfireMode crossfireMode; ///< Desired Crossfire mode +} AGSDX11ExtensionParams; + +/// The struct to hold all the returned parameters from the device creation call +typedef struct AGSDX11ReturnedParams +{ + ID3D11Device* pDevice; ///< The newly created device + ID3D11DeviceContext* pImmediateContext; ///< The newly created immediate device context + IDXGISwapChain* pSwapChain; ///< The newly created swap chain. This is only created if a valid pSwapChainDesc is supplied in AGSDX11DeviceCreationParams. + D3D_FEATURE_LEVEL featureLevel; ///< The feature level supported by the newly created device + typedef struct ExtensionsSupported /// Extensions for DX11 + { + unsigned int quadList : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int screenRectList : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int uavOverlap : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int depthBoundsTest : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int multiDrawIndirect : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int multiDrawIndirectCountIndirect : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int crossfireAPI : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int createShaderControls : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. + unsigned int intrinsics16 : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. ReadFirstLane, ReadLane, LaneID, Swizzle, Ballot, MBCount, Med3, Barycentrics + unsigned int multiView : 1; ///< Supported in Radeon Software Version 16.12.1 onwards. + unsigned int intrinsics17 : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. WaveReduce, WaveScan + unsigned int appRegistration : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. + unsigned int breadcrumbMarkers : 1; ///< Supported in Radeon Software Version 17.11.1 onwards. + unsigned int MDIDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. + unsigned int UAVOverlapDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. + unsigned int depthBoundsDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. + unsigned int intrinsics19 : 1; ///< Supported in Radeon Software Version 19.12.2 onwards. DrawIndex, AtomicU64 + unsigned int getWaveSize : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. + unsigned int baseVertex : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. + unsigned int baseInstance : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. + unsigned int padding : 12; ///< Reserved + } ExtensionsSupported; + ExtensionsSupported extensionsSupported; ///< List of supported extensions + unsigned int crossfireGPUCount; ///< The number of GPUs that are active for this app + void* breadcrumbBuffer; ///< The CPU buffer returned if the initialization of the breadcrumb was successful +} AGSDX11ReturnedParams; + +/// +/// Function used to create a D3D11 device with additional AMD-specific initialization parameters. +/// +/// When using the HLSL shader extensions please note: +/// * The shader compiler should not use the D3DCOMPILE_SKIP_OPTIMIZATION (/Od) option, otherwise it will not work. +/// * The shader compiler needs D3DCOMPILE_ENABLE_STRICTNESS (/Ges) enabled. +/// +/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize +/// \param [in] creationParams Pointer to the struct to specify the existing DX11 device creation parameters. +/// \param [in] extensionParams Optional pointer to the struct to specify DX11 additional device creation parameters. +/// \param [out] returnedParams Pointer to struct to hold all the returned parameters from the call. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateDevice( AGSContext* context, const AGSDX11DeviceCreationParams* creationParams, const AGSDX11ExtensionParams* extensionParams, AGSDX11ReturnedParams* returnedParams ); + +/// +/// Function to destroy the D3D11 device and its immediate context. +/// This call will also cleanup any AMD-specific driver extensions for D3D11. +/// +/// \param [in] context Pointer to a context. +/// \param [in] device Pointer to the D3D11 device. +/// \param [out] deviceReferences Optional pointer to an unsigned int that will be set to the value returned from device->Release(). +/// \param [in] immediateContext Pointer to the D3D11 immediate device context. +/// \param [out] immediateContextReferences Optional pointer to an unsigned int that will be set to the value returned from immediateContext->Release(). +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_DestroyDevice( AGSContext* context, ID3D11Device* device, unsigned int* deviceReferences, ID3D11DeviceContext* immediateContext, unsigned int* immediateContextReferences ); + +/// @} + +/// \defgroup breadcrumbs Breadcrumb API +/// API for writing top-of-pipe and bottom-of-pipe markers to help track down GPU hangs. +/// +/// The API is available if the \ref AGSDX11ReturnedParams::ExtensionsSupported::breadcrumbMarkers is present. +/// +/// To use the API, a non zero value needs to be specificed in \ref AGSDX11ExtensionParams::numBreadcrumbMarkers. This enables the API (if available) and allocates a system memory buffer +/// which is returned to the user in \ref AGSDX11ReturnedParams::breadcrumbBuffer. +/// +/// The user can now write markers before and after draw calls using \ref agsDriverExtensionsDX11_WriteBreadcrumb. +/// +/// \section background Background +/// +/// A top-of-pipe (TOP) command is scheduled for execution as soon as the command processor (CP) reaches the command. +/// A bottom-of-pipe (BOP) command is scheduled for execution once the previous rendering commands (draw and dispatch) finish execution. +/// TOP and BOP commands do not block CP. i.e. the CP schedules the command for execution then proceeds to the next command without waiting. +/// To effectively use TOP and BOP commands, it is important to understand how they interact with rendering commands: +/// +/// When the CP encounters a rendering command it queues it for execution and moves to the next command. The queued rendering commands are issued in order. +/// There can be multiple rendering commands running in parallel. When a rendering command is issued we say it is at the top of the pipe. When a rendering command +/// finishes execution we say it has reached the bottom of the pipe. +/// +/// A BOP command remains in a waiting queue and is executed once prior rendering commands finish. The queue of BOP commands is limited to 64 entries in GCN generation 1, 2, 3, 4 and 5. +/// If the 64 limit is reached the CP will stop queueing BOP commands and also rendering commands. Developers should limit the number of BOP commands that write markers to avoid contention. +/// In general, developers should limit both TOP and BOP commands to avoid stalling the CP. +/// +/// \subsection eg1 Example 1: +/// +/// \code{.cpp} +/// // Start of a command buffer +/// WriteMarker(TopOfPipe, 1) +/// WriteMarker(BottomOfPipe, 2) +/// WriteMarker(BottomOfPipe, 3) +/// DrawX +/// WriteMarker(BottomOfPipe, 4) +/// WriteMarker(BottomOfPipe, 5) +/// WriteMarker(TopOfPipe, 6) +/// // End of command buffer +/// \endcode +/// +/// In the above example, the CP writes markers 1, 2 and 3 without waiting: +/// Marker 1 is TOP so it's independent from other commands +/// There's no wait for marker 2 and 3 because there are no draws preceding the BOP commands +/// Marker 4 is only written once DrawX finishes execution +/// Marker 5 doesn't wait for additional draws so it is written right after marker 4 +/// Marker 6 can be written as soon as the CP reaches the command. For instance, it is very possible that CP writes marker 6 while DrawX +/// is running and therefore marker 6 gets written before markers 4 and 5 +/// +/// \subsection eg2 Example 2: +/// +/// \code{.cpp} +/// WriteMarker(TopOfPipe, 1) +/// DrawX +/// WriteMarker(BottomOfPipe, 2) +/// WriteMarker(TopOfPipe, 3) +/// DrawY +/// WriteMarker(BottomOfPipe, 4) +/// \endcode +/// +/// In this example marker 1 is written before the start of DrawX +/// Marker 2 is written once DrawX finishes execution +/// Similarly marker 3 is written before the start of DrawY +/// Marker 4 is written once DrawY finishes execution +/// In case of a GPU hang, if markers 1 and 3 are written but markers 2 and 4 are missing we can conclude that: +/// The CP has reached both DrawX and DrawY commands since marker 1 and 3 are present +/// The fact that marker 2 and 4 are missing means that either DrawX is hanging while DrawY is at the top of the pipe or both DrawX and DrawY +/// started and both are simultaneously hanging +/// +/// \subsection eg3 Example 3: +/// +/// \code{.cpp} +/// // Start of a command buffer +/// WriteMarker(BottomOfPipe, 1) +/// DrawX +/// WriteMarker(BottomOfPipe, 2) +/// DrawY +/// WriteMarker(BottomOfPipe, 3) +/// DrawZ +/// WriteMarker(BottomOfPipe, 4) +/// // End of command buffer +/// \endcode +/// +/// In this example marker 1 is written before the start of DrawX +/// Marker 2 is written once DrawX finishes +/// Marker 3 is written once DrawY finishes +/// Marker 4 is written once DrawZ finishes +/// If the GPU hangs and only marker 1 is written we can conclude that the hang is happening in either DrawX, DrawY or DrawZ +/// If the GPU hangs and only marker 1 and 2 are written we can conclude that the hang is happening in DrawY or DrawZ +/// If the GPU hangs and only marker 4 is missing we can conclude that the hang is happening in DrawZ +/// +/// \subsection eg4 Example 4: +/// +/// \code{.cpp} +/// Start of a command buffer +/// WriteMarker(TopOfPipe, 1) +/// DrawX +/// WriteMarker(TopOfPipe, 2) +/// DrawY +/// WriteMarker(TopOfPipe, 3) +/// DrawZ +/// // End of command buffer +/// \endcode +/// +/// In this example, in case the GPU hangs and only marker 1 is written we can conclude that the hang is happening in DrawX +/// In case the GPU hangs and only marker 1 and 2 are written we can conclude that the hang is happening in DrawX or DrawY +/// In case the GPU hangs and all 3 markers are written we can conclude that the hang is happening in any of DrawX, DrawY or DrawZ +/// +/// \subsection eg5 Example 5: +/// +/// \code{.cpp} +/// DrawX +/// WriteMarker(TopOfPipe, 1) +/// WriteMarker(BottomOfPipe, 2) +/// DrawY +/// WriteMarker(TopOfPipe, 3) +/// WriteMarker(BottomOfPipe, 4) +/// \endcode +/// +/// Marker 1 is written right after DrawX is queued for execution. +/// Marker 2 is only written once DrawX finishes execution. +/// Marker 3 is written right after DrawY is queued for execution. +/// Marker 4 is only written once DrawY finishes execution +/// If marker 1 is written we would know that the CP has reached the command DrawX (DrawX at the top of the pipe). +/// If marker 2 is written we can say that DrawX has finished execution (DrawX at the bottom of the pipe). +/// In case the GPU hangs and only marker 1 and 3 are written we can conclude that the hang is happening in DrawX or DrawY +/// In case the GPU hangs and only marker 1 is written we can conclude that the hang is happening in DrawX +/// In case the GPU hangs and only marker 4 is missing we can conclude that the hang is happening in DrawY +/// +/// \section data Retrieving GPU Data +/// +/// In the event of a GPU hang, the user can inspect the system memory buffer to determine which draw has caused the hang. +/// For example: +/// \code{.cpp} +/// // Force the work to be flushed to prevent CPU ahead of GPU +/// g_pImmediateContext->Flush(); +/// +/// // Present the information rendered to the back buffer to the front buffer (the screen) +/// HRESULT hr = g_pSwapChain->Present( 0, 0 ); +/// +/// // Read the marker data buffer once detect device lost +/// if ( hr != S_OK ) +/// { +/// for (UINT i = 0; i < g_NumMarkerWritten; i++) +/// { +/// UINT64* pTempData; +/// pTempData = static_cast(pMarkerBuffer); +/// +/// // Write the marker data to file +/// ofs << i << "\r\n"; +/// ofs << std::hex << *(pTempData + i * 2) << "\r\n"; +/// ofs << std::hex << *(pTempData + (i * 2 + 1)) << "\r\n"; +/// +/// WCHAR s1[256]; +/// setlocale(LC_NUMERIC, "en_US.iso88591"); +/// +/// // Output the marker data to console +/// swprintf(s1, 256, L" The Draw count is %d; The Top maker is % 016llX and the Bottom marker is % 016llX \r\n", i, *(pTempData + i * 2), *(pTempData + (i * 2 + 1))); +/// +/// OutputDebugStringW(s1); +/// } +/// } +/// \endcode +/// +/// The console output would resemble something like: +/// \code{.cpp} +/// D3D11: Removing Device. +/// D3D11 ERROR: ID3D11Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DEVICE_HUNG: The Device took an unreasonable amount of time to execute its commands, or the hardware crashed/hung. As a result, the TDR (Timeout Detection and Recovery) mechanism has been triggered. The current Device Context was executing commands when the hang occurred. The application may want to respawn and fallback to less aggressive use of the display hardware). [ EXECUTION ERROR #378: DEVICE_REMOVAL_PROCESS_AT_FAULT] +/// The Draw count is 0; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF +/// The Draw count is 1; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF +/// The Draw count is 2; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF +/// The Draw count is 3; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF +/// The Draw count is 4; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF +/// The Draw count is 5; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD +/// The Draw count is 6; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD +/// The Draw count is 7; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD +/// \endcode +/// +/// @{ + +/// The breadcrumb marker struct used by \ref agsDriverExtensionsDX11_WriteBreadcrumb +typedef struct AGSBreadcrumbMarker +{ + /// The marker type + typedef enum Type + { + TopOfPipe = 0, ///< Top-of-pipe marker + BottomOfPipe = 1 ///< Bottom-of-pipe marker + } Type; + + unsigned long long markerData; ///< The user data to write. + Type type; ///< Whether this marker is top or bottom of pipe. + unsigned int index; ///< The index of the marker. This should be less than the value specified in \ref AGSDX11ExtensionParams::numBreadcrumbMarkers +} AGSBreadcrumbMarker; + +/// +/// Function to write a breadcrumb marker. +/// +/// This method inserts a write marker operation in the GPU command stream. In the case where the GPU is hanging the write +/// command will never be reached and the marker will never get written to memory. +/// +/// In order to use this function, \ref AGSDX11ExtensionParams::numBreadcrumbMarkers must be set to a non zero value. +/// +/// \param [in] context Pointer to a context. +/// \param [in] marker Pointer to a marker. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_WriteBreadcrumb( AGSContext* context, const AGSBreadcrumbMarker* marker ); + +/// @} + +/// \defgroup dx11Topology Extended Topology +/// API for primitive topologies +/// @{ + +/// Additional topologies supported via extensions +typedef enum AGSPrimitiveTopologyDX11 +{ + AGS_PRIMITIVE_TOPOLOGY_QUADLIST = 7, ///< Quad list + AGS_PRIMITIVE_TOPOLOGY_SCREENRECTLIST = 9 ///< Screen rect list +} AGSPrimitiveTopologyDX11; + +/// +/// Function used to set the primitive topology. If you are using any of the extended topology types, then this function should +/// be called to set ALL topology types. +/// +/// The Quad List extension is a convenient way to submit quads without using an index buffer. Note that this still submits two triangles at the driver level. +/// In order to use this function, AGS must already be initialized and agsDriverExtensionsDX11_Init must have been called successfully. +/// +/// The Screen Rect extension, which is only available on GCN hardware, allows the user to pass in three of the four corners of a rectangle. +/// The hardware then uses the bounding box of the vertices to rasterize the rectangle primitive (i.e. as a rectangle rather than two triangles). +/// \note Note that this will not return valid interpolated values, only valid SV_Position values. +/// \note If either the Quad List or Screen Rect extension are used, then agsDriverExtensionsDX11_IASetPrimitiveTopology should be called in place of the native DirectX11 equivalent all the time. +/// +/// \param [in] context Pointer to a context. +/// \param [in] topology The topology to set on the D3D11 device. This can be either an AGS-defined topology such as AGS_PRIMITIVE_TOPOLOGY_QUADLIST +/// or a standard D3D-defined topology such as D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP. +/// NB. the AGS-defined types will require casting to a D3D_PRIMITIVE_TOPOLOGY type. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_IASetPrimitiveTopology( AGSContext* context, D3D_PRIMITIVE_TOPOLOGY topology ); + +/// @} + +/// \defgroup dx11UAVOverlap UAV Overlap +/// API for enabling overlapping UAV writes +/// +/// The AMD DX11 driver will automatically track resource usage and insert barriers as necessary to clear read-after-write (RAW) and write-after-write (WAW) +/// hazards. The UAV overlap extension allows applications to indicate to the driver it can skip inserting barriers for UAV resources used in +/// dispatches and draws within the \ref agsDriverExtensionsDX11_BeginUAVOverlap/ \ref agsDriverExtensionsDX11_EndUAVOverlap calls. This can be useful for applications to allow +/// multiple back-to-back dispatches or draws in flight even if they are accessing the same UAV resource but the data written or read does not overlap within the resource. +/// +/// Usage would be as follows: +/// \code{.cpp} +/// m_device->Dispatch( ... ); // First call that writes to the UAV +/// +/// // Disable automatic WAW syncs +/// agsDriverExtensionsDX11_BeginUAVOverlap( m_agsContext ); +/// +/// // Submit other dispatches that write to the same UAV concurrently +/// m_device->Dispatch( ... ); +/// m_device->Dispatch( ... ); +/// m_device->Dispatch( ... ); +/// +/// // Reenable automatic WAW syncs +/// agsDriverExtensionsDX11_EndUAVOverlap( m_agsContext ); +/// \endcode +/// @{ + +/// +/// Function used indicate to the driver the start of the overlap scope. +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// with the AGS_DX11_EXTENSION_DEFERRED_CONTEXTS bit. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_BeginUAVOverlap( AGSContext* context, ID3D11DeviceContext* dxContext ); + +/// +/// Function used indicate to the driver the end of the overlap scope. +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// with the AGS_DX11_EXTENSION_DEFERRED_CONTEXTS bit. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_EndUAVOverlap( AGSContext* context, ID3D11DeviceContext* dxContext ); + +/// @} + +/// \defgroup dx11DepthBoundsTest Depth Bounds Test +/// API for enabling depth bounds testing +/// @{ + +/// +/// Function used to set the depth bounds test extension +/// +/// \param [in] context Pointer to a context +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// \param [in] enabled Whether to enable or disable the depth bounds testing. If disabled, the next two args are ignored. +/// \param [in] minDepth The near depth range to clip against. +/// \param [in] maxDepth The far depth range to clip against. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetDepthBounds( AGSContext* context, ID3D11DeviceContext* dxContext, bool enabled, float minDepth, float maxDepth ); + +/// @} + +/// \defgroup mdi Multi Draw Indirect (MDI) +/// API for dispatching multiple instanced draw commands. +/// The multi draw indirect extensions allow multiple sets of DrawInstancedIndirect to be submitted in one API call. +/// The draw calls are issued on the GPU's command processor (CP), potentially saving the significant CPU overheads incurred by submitting the equivalent draw calls on the CPU. +/// +/// The extension allows the following code: +/// \code{.cpp} +/// // Submit n batches of DrawIndirect calls +/// for ( int i = 0; i < n; i++ ) +/// deviceContext->DrawIndexedInstancedIndirect( buffer, i * sizeof( cmd ) ); +/// \endcode +/// To be replaced by the following call: +/// \code{.cpp} +/// // Submit all n batches in one call +/// agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect( m_agsContext, deviceContext, n, buffer, 0, sizeof( cmd ) ); +/// \endcode +/// +/// The buffer used for the indirect args must be of the following formats: +/// \code{.cpp} +/// // Buffer layout for agsDriverExtensions_MultiDrawInstancedIndirect +/// struct DrawInstancedIndirectArgs +/// { +/// UINT VertexCountPerInstance; +/// UINT InstanceCount; +/// UINT StartVertexLocation; +/// UINT StartInstanceLocation; +/// }; +/// +/// // Buffer layout for agsDriverExtensions_MultiDrawIndexedInstancedIndirect +/// struct DrawIndexedInstancedIndirectArgs +/// { +/// UINT IndexCountPerInstance; +/// UINT InstanceCount; +/// UINT StartIndexLocation; +/// UINT BaseVertexLocation; +/// UINT StartInstanceLocation; +/// }; +/// \endcode +/// +/// Example usage can be seen in AMD's GeometryFX (https://github.com/GPUOpen-Effects/GeometryFX). In particular, in this file: https://github.com/GPUOpen-Effects/GeometryFX/blob/master/amd_geometryfx/src/AMD_GeometryFX_Filtering.cpp +/// +/// @{ + +/// +/// Function used to submit a batch of draws via MultiDrawIndirect +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// \param [in] drawCount The number of draws. +/// \param [in] pBufferForArgs The args buffer. +/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. +/// \param [in] byteStrideForArgs The per element stride of the args buffer. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawInstancedIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, unsigned int drawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); + +/// +/// Function used to submit a batch of draws via MultiDrawIndirect +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// \param [in] drawCount The number of draws. +/// \param [in] pBufferForArgs The args buffer. +/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. +/// \param [in] byteStrideForArgs The per element stride of the args buffer. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, unsigned int drawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); + +/// +/// Function used to submit a batch of draws via MultiDrawIndirect +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// \param [in] pBufferForDrawCount The draw count buffer. +/// \param [in] alignedByteOffsetForDrawCount The offset into the draw count buffer. +/// \param [in] pBufferForArgs The args buffer. +/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. +/// \param [in] byteStrideForArgs The per element stride of the args buffer. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawInstancedIndirectCountIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, ID3D11Buffer* pBufferForDrawCount, unsigned int alignedByteOffsetForDrawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); + +/// +/// Function used to submit a batch of draws via MultiDrawIndirect +/// +/// \param [in] context Pointer to a context. +/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. +/// \param [in] pBufferForDrawCount The draw count buffer. +/// \param [in] alignedByteOffsetForDrawCount The offset into the draw count buffer. +/// \param [in] pBufferForArgs The args buffer. +/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. +/// \param [in] byteStrideForArgs The per element stride of the args buffer. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirectCountIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, ID3D11Buffer* pBufferForDrawCount, unsigned int alignedByteOffsetForDrawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); + +/// @} + +/// \defgroup shadercompiler Shader Compiler Controls +/// API for controlling DirectX11 shader compilation. +/// Check support for this feature using the AGS_DX11_EXTENSION_CREATE_SHADER_CONTROLS bit. +/// Supported in Radeon Software Version 16.9.2 (driver version 16.40.2311) onwards. +/// @{ + +/// +/// This method can be used to limit the maximum number of threads the driver uses for asynchronous shader compilation. +/// Setting it to 0 will disable asynchronous compilation completely and force the shaders to be compiled "inline" on the threads that call Create*Shader. +/// +/// This method can only be called before any shaders are created and being compiled by the driver. +/// If this method is called after shaders have been created the function will return AGS_FAILURE. +/// This function only sets an upper limit.The driver may create fewer threads than allowed by this function. +/// +/// \param [in] context Pointer to a context. +/// \param [in] numberOfThreads The maximum number of threads to use. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetMaxAsyncCompileThreadCount( AGSContext* context, unsigned int numberOfThreads ); + +/// +/// This method can be used to determine the total number of asynchronous shader compile jobs that are either +/// queued for waiting for compilation or being compiled by the driver's asynchronous compilation threads. +/// This method can be called at any during the lifetime of the driver. +/// +/// \param [in] context Pointer to a context. +/// \param [out] numberOfJobs Pointer to the number of jobs in flight currently. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NumPendingAsyncCompileJobs( AGSContext* context, unsigned int* numberOfJobs ); + +/// +/// This method can be used to enable or disable the disk based shader cache. +/// Enabling/disabling the disk cache is not supported if is it disabled explicitly via Radeon Settings or by an app profile. +/// Calling this method under these conditions will result in AGS_FAILURE being returned. +/// It is recommended that this method be called before any shaders are created by the application and being compiled by the driver. +/// Doing so at any other time may result in the cache being left in an inconsistent state. +/// +/// \param [in] context Pointer to a context. +/// \param [in] enable Whether to enable the disk cache. 0 to disable, 1 to enable. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetDiskShaderCacheEnabled( AGSContext* context, int enable ); + +/// @} + +/// \defgroup multiview Multiview +/// API for multiview broadcasting. +/// Check support for this feature using the AGS_DX11_EXTENSION_MULTIVIEW bit. +/// Supported in Radeon Software Version 16.12.1 (driver version 16.50.2001) onwards. +/// @{ + +/// +/// Function to control draw calls replication to multiple viewports and RT slices. +/// Setting any mask to 0 disables draw replication. +/// +/// \param [in] context Pointer to a context. +/// \param [in] vpMask Viewport control bit mask. +/// \param [in] rtSliceMask RT slice control bit mask. +/// \param [in] vpMaskPerRtSliceEnabled If 0, 16 lower bits of vpMask apply to all RT slices; if 1 each 16 bits of 64-bit mask apply to corresponding 4 RT slices. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetViewBroadcastMasks( AGSContext* context, unsigned long long vpMask, unsigned long long rtSliceMask, int vpMaskPerRtSliceEnabled ); + +/// +/// Function returns max number of supported clip rectangles. +/// +/// \param [in] context Pointer to a context. +/// \param [out] maxRectCount Returned max number of clip rectangles. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_GetMaxClipRects( AGSContext* context, unsigned int* maxRectCount ); + +/// The clip rectangle struct used by \ref agsDriverExtensionsDX11_SetClipRects +typedef struct AGSClipRect +{ + /// The inclusion mode for the rect + typedef enum Mode + { + ClipRectIncluded = 0, ///< Include the rect + ClipRectExcluded = 1 ///< Exclude the rect + } Mode; + + Mode mode; ///< Include/exclude rect region + AGSRect rect; ///< The rect to include/exclude +} AGSClipRect; + +/// +/// Function sets clip rectangles. +/// +/// \param [in] context Pointer to a context. +/// \param [in] clipRectCount Number of specified clip rectangles. Use 0 to disable clip rectangles. +/// \param [in] clipRects Array of clip rectangles. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetClipRects( AGSContext* context, unsigned int clipRectCount, const AGSClipRect* clipRects ); + +/// @} + +/// \defgroup cfxapi Explicit Crossfire API +/// API for explicit control over Crossfire +/// @{ + +/// The Crossfire API transfer types +typedef enum AGSAfrTransferType +{ + AGS_AFR_TRANSFER_DEFAULT = 0, ///< Default Crossfire driver resource tracking + AGS_AFR_TRANSFER_DISABLE = 1, ///< Turn off driver resource tracking + AGS_AFR_TRANSFER_1STEP_P2P = 2, ///< App controlled GPU to next GPU transfer + AGS_AFR_TRANSFER_2STEP_NO_BROADCAST = 3, ///< App controlled GPU to next GPU transfer using intermediate system memory + AGS_AFR_TRANSFER_2STEP_WITH_BROADCAST = 4, ///< App controlled GPU to all render GPUs transfer using intermediate system memory +} AGSAfrTransferType; + +/// The Crossfire API transfer engines +typedef enum AGSAfrTransferEngine +{ + AGS_AFR_TRANSFERENGINE_DEFAULT = 0, ///< Use default engine for Crossfire API transfers + AGS_AFR_TRANSFERENGINE_3D_ENGINE = 1, ///< Use 3D engine for Crossfire API transfers + AGS_AFR_TRANSFERENGINE_COPY_ENGINE = 2, ///< Use Copy engine for Crossfire API transfers +} AGSAfrTransferEngine; + +/// +/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. +/// +/// \param [in] context Pointer to a context. +/// \param [in] desc Pointer to the D3D11 resource description. +/// \param [in] initialData Optional pointer to the initializing data for the resource. +/// \param [out] buffer Returned pointer to the resource. +/// \param [in] transferType The transfer behavior. +/// \param [in] transferEngine The transfer engine to use. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateBuffer( AGSContext* context, const D3D11_BUFFER_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Buffer** buffer, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); + +/// +/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. +/// +/// \param [in] context Pointer to a context. +/// \param [in] desc Pointer to the D3D11 resource description. +/// \param [in] initialData Optional pointer to the initializing data for the resource. +/// \param [out] texture1D Returned pointer to the resource. +/// \param [in] transferType The transfer behavior. +/// \param [in] transferEngine The transfer engine to use. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture1D( AGSContext* context, const D3D11_TEXTURE1D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture1D** texture1D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); + +/// +/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. +/// +/// \param [in] context Pointer to a context. +/// \param [in] desc Pointer to the D3D11 resource description. +/// \param [in] initialData Optional pointer to the initializing data for the resource. +/// \param [out] texture2D Returned pointer to the resource. +/// \param [in] transferType The transfer behavior. +/// \param [in] transferEngine The transfer engine to use. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture2D( AGSContext* context, const D3D11_TEXTURE2D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture2D** texture2D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); + +/// +/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. +/// +/// \param [in] context Pointer to a context. +/// \param [in] desc Pointer to the D3D11 resource description. +/// \param [in] initialData Optional pointer to the initializing data for the resource. +/// \param [out] texture3D Returned pointer to the resource. +/// \param [in] transferType The transfer behavior. +/// \param [in] transferEngine The transfer engine to use. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture3D( AGSContext* context, const D3D11_TEXTURE3D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture3D** texture3D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); + +/// +/// Function to notify the driver that we have finished writing to the resource this frame. +/// This will initiate a transfer for AGS_AFR_TRANSFER_1STEP_P2P, +/// AGS_AFR_TRANSFER_2STEP_NO_BROADCAST, and AGS_AFR_TRANSFER_2STEP_WITH_BROADCAST. +/// +/// \param [in] context Pointer to a context. +/// \param [in] resource Pointer to the resource. +/// \param [in] transferRegions An array of transfer regions (can be null to specify the whole area). +/// \param [in] subresourceArray An array of subresource indices (can be null to specify all subresources). +/// \param [in] numSubresources The number of subresources in subresourceArray OR number of transferRegions. Use 0 to specify ALL subresources and one transferRegion (which may be null if specifying the whole area). +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceEndWrites( AGSContext* context, ID3D11Resource* resource, const D3D11_RECT* transferRegions, const unsigned int* subresourceArray, unsigned int numSubresources ); + +/// +/// This will notify the driver that the app will begin read/write access to the resource. +/// +/// \param [in] context Pointer to a context. +/// \param [in] resource Pointer to the resource. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceBeginAllAccess( AGSContext* context, ID3D11Resource* resource ); + +/// +/// This is used for AGS_AFR_TRANSFER_1STEP_P2P to notify when it is safe to initiate a transfer. +/// This call in frame N-(NumGpus-1) allows a 1 step P2P in frame N to start. +/// This should be called after agsDriverExtensionsDX11_NotifyResourceEndWrites. +/// +/// \param [in] context Pointer to a context. +/// \param [in] resource Pointer to the resource. +/// +AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceEndAllAccess( AGSContext* context, ID3D11Resource* resource ); + +/// @} + +/// @} + +/// \defgroup typedefs Function pointer typedefs +/// List of function pointer typedefs for the API +/// @{ + +typedef AMD_AGS_API AGSDriverVersionResult (*AGS_CHECKDRIVERVERSION)( const char*, unsigned int ); ///< \ref agsCheckDriverVersion +typedef AMD_AGS_API int (*AGS_GETVERSIONNUMBER)(); ///< \ref agsGetVersionNumber +typedef AMD_AGS_API AGSReturnCode (*AGS_INITIALIZE)( int, const AGSConfiguration*, AGSContext**, AGSGPUInfo* ); ///< \ref agsInitialize +typedef AMD_AGS_API AGSReturnCode (*AGS_DEINITIALIZE)( AGSContext* ); ///< \ref agsDeInitialize +typedef AMD_AGS_API AGSReturnCode (*AGS_SETDISPLAYMODE)( AGSContext*, int, int, const AGSDisplaySettings* ); ///< \ref agsSetDisplayMode +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_CREATEDEVICE)( AGSContext*, const AGSDX12DeviceCreationParams*, const AGSDX12ExtensionParams*, AGSDX12ReturnedParams* ); ///< \ref agsDriverExtensionsDX12_CreateDevice +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_DESTROYDEVICE)( AGSContext*, ID3D12Device*, unsigned int* ); ///< \ref agsDriverExtensionsDX12_DestroyDevice +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_PUSHMARKER)( AGSContext*, ID3D12GraphicsCommandList*, const char* ); ///< \ref agsDriverExtensionsDX12_PushMarker +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_POPMARKER)( AGSContext*, ID3D12GraphicsCommandList* ); ///< \ref agsDriverExtensionsDX12_PopMarker +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_SETMARKER)( AGSContext*, ID3D12GraphicsCommandList*, const char* ); ///< \ref agsDriverExtensionsDX12_SetMarker +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATEDEVICE)( AGSContext*, const AGSDX11DeviceCreationParams*, const AGSDX11ExtensionParams*, AGSDX11ReturnedParams* ); ///< \ref agsDriverExtensionsDX11_CreateDevice +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_DESTROYDEVICE)( AGSContext*, ID3D11Device*, unsigned int*, ID3D11DeviceContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_DestroyDevice +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_WRITEBREADCRUMB)( AGSContext*, const AGSBreadcrumbMarker* ); ///< \ref agsDriverExtensionsDX11_WriteBreadcrumb +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_IASETPRIMITIVETOPOLOGY)( AGSContext*, enum D3D_PRIMITIVE_TOPOLOGY ); ///< \ref agsDriverExtensionsDX11_IASetPrimitiveTopology +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_BEGINUAVOVERLAP)( AGSContext*, ID3D11DeviceContext* ); ///< \ref agsDriverExtensionsDX11_BeginUAVOverlap +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_ENDUAVOVERLAP)( AGSContext*, ID3D11DeviceContext* ); ///< \ref agsDriverExtensionsDX11_EndUAVOverlap +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETDEPTHBOUNDS)( AGSContext*, ID3D11DeviceContext*, bool, float, float ); ///< \ref agsDriverExtensionsDX11_SetDepthBounds +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINSTANCEDINDIRECT)( AGSContext*, ID3D11DeviceContext*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawInstancedIndirect +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINDEXEDINSTANCEDINDIRECT)( AGSContext*, ID3D11DeviceContext*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINSTANCEDINDIRECTCOUNTINDIRECT)( AGSContext*, ID3D11DeviceContext*, ID3D11Buffer*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawInstancedIndirectCountIndirect +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINDEXEDINSTANCEDINDIRECTCOUNTINDIRECT)( AGSContext*, ID3D11DeviceContext*, ID3D11Buffer*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirectCountIndirect +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETMAXASYNCCOMPILETHREADCOUNT)( AGSContext*, unsigned int ); ///< \ref agsDriverExtensionsDX11_SetMaxAsyncCompileThreadCount +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NUMPENDINGASYNCOMPILEJOBS)( AGSContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_NumPendingAsyncCompileJobs +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETDISKSHADERCACHEENABLED)( AGSContext*, int ); ///< \ref agsDriverExtensionsDX11_SetDiskShaderCacheEnabled +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETVIEWBROADCASTMASKS)( AGSContext*, unsigned long long, unsigned long long, int ); ///< \ref agsDriverExtensionsDX11_SetViewBroadcastMasks +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_GETMAXCLIPRECTS)( AGSContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_GetMaxClipRects +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETCLIPRECTS)( AGSContext*, unsigned int, const AGSClipRect* ); ///< \ref agsDriverExtensionsDX11_SetClipRects +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATEBUFFER)( AGSContext*, const D3D11_BUFFER_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Buffer**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateBuffer +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE1D)( AGSContext*, const D3D11_TEXTURE1D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture1D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture1D +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE2D)( AGSContext*, const D3D11_TEXTURE2D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture2D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture2D +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE3D)( AGSContext*, const D3D11_TEXTURE3D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture3D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture3D +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEENDWRITES)( AGSContext*, ID3D11Resource*, const D3D11_RECT*, const unsigned int*, unsigned int ); ///< \ref agsDriverExtensionsDX11_NotifyResourceEndWrites +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEBEGINALLACCESS)( AGSContext*, ID3D11Resource* ); ///< \ref agsDriverExtensionsDX11_NotifyResourceBeginAllAccess +typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEENDALLACCESS)( AGSContext*, ID3D11Resource* ); ///< \ref agsDriverExtensionsDX11_NotifyResourceEndAllAccess +/// @} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // AMD_AGS_H diff --git a/src/3rdparty/ags/repo.json b/src/3rdparty/ags/repo.json new file mode 100644 index 0000000000..b00f125cdd --- /dev/null +++ b/src/3rdparty/ags/repo.json @@ -0,0 +1,6 @@ +{ + "home": "https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK", + "license": "MIT (embeded in source)", + "version": "AGS v6.2.0", + "author": "Advanced Micro Devices, Inc" +} diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c new file mode 100644 index 0000000000..272a85db5b --- /dev/null +++ b/src/detection/gpu/gpu_amd.c @@ -0,0 +1,67 @@ +#include "gpu_driver_specific.h" + +// Everything detected in this file is static. +// The real time monitoring requires ADLX, whose interface is much more complicated than AGS +// Whoever has AMD graphic cards interested in this may contribute +// * ADLX (AMD Device Library eXtra): https://github.com/GPUOpen-LibrariesAndSDKs/ADLX + +#include "3rdparty/ags/amd_ags.h" +#include "common/library.h" +#include "util/mallocHelper.h" + +const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName) +{ + static bool inited = false; + static AGSGPUInfo gpuInfo; + + if (!inited) + { + inited = true; + FF_LIBRARY_LOAD(libags, NULL, "dlopen amd_ags failed", soName , 1); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsInitialize) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libags, agsDeInitialize) + + struct AGSContext* apiHandle; + if (ffagsInitialize(AGS_CURRENT_VERSION, NULL, &apiHandle, &gpuInfo) != AGS_SUCCESS) + return "loading ags library failed"; + + ffagsDeInitialize(apiHandle); + } + + if (!gpuInfo.numDevices == 0) + return "loading ags library failed or no AMD gpus found"; + + AGSDeviceInfo* device = NULL; + + for (int iDev = 0; iDev < gpuInfo.numDevices; iDev++) + { + if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID) + { + if ( + cond->pciDeviceId.deviceId == (uint32_t) gpuInfo.devices[iDev].deviceId && + cond->pciDeviceId.vendorId == (uint32_t) gpuInfo.devices[iDev].vendorId && + cond->pciDeviceId.revId == (uint32_t) gpuInfo.devices[iDev].revisionId) + { + device = &gpuInfo.devices[iDev]; + break; + } + } + } + + if (!device) + return "Device not found"; + + if (result.coreCount) + *result.coreCount = (uint32_t) device->numCUs; + + if (result.memory) + { + result.memory->total = device->localMemoryInBytes; + result.memory->used = FF_GPU_VMEM_SIZE_UNSET; + } + + if (result.frequency) + *result.frequency = device->coreClock / 1000.; // Maximum frequency + + return NULL; +} diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 9205c0954b..8405e0de0e 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -46,3 +46,4 @@ typedef struct FFGpuDriverResult const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); +const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index fd0ba1046d..db8e593792 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -10,6 +10,41 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name) return ffStrbufEqual(&gpu->name, name); } +static inline bool getDriverSpecificDetectionFn(const char* vendor, __typeof__(&ffDetectNvidiaGpuInfo)* pDetectFn, const char** pDllName) +{ + if (vendor == FF_GPU_VENDOR_NAME_NVIDIA) + { + *pDetectFn = ffDetectNvidiaGpuInfo; + *pDllName = "nvml.dll"; + } + else if (vendor == FF_GPU_VENDOR_NAME_INTEL) + { + *pDetectFn = ffDetectIntelGpuInfo; + #ifdef _WIN64 + *pDllName = "ControlLib.dll"; + #else + *pDllName = "ControlLib32.dll"; + #endif + } + else if (vendor == FF_GPU_VENDOR_NAME_AMD) + { + *pDetectFn = ffDetectAmdGpuInfo; + #ifdef _WIN64 + *pDllName = "amd_ags_x64.dll"; + #else + *pDllName = "amd_ags_x86.dll"; + #endif + } + else + { + *pDetectFn = NULL; + *pDllName = NULL; + return false; + } + + return true; +} + const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpus) { DISPLAY_DEVICEW displayDevice = { .cb = sizeof(displayDevice) }; @@ -55,12 +90,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL); ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL); - if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - else if(ffStrbufContainS(&gpu->vendor, "Intel")) + if (ffStrbufContainS(&gpu->vendor, "Intel")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if(ffStrbufContainS(&gpu->vendor, "NVIDIA")) + else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}")); FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; @@ -89,15 +124,17 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } } - if ((gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA || gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) && - (options->temp || options->driverSpecific)) + __typeof__(&ffDetectNvidiaGpuInfo) detectFn; + const char* dllName; + + if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { uint32_t vendorId, deviceId, subSystemId, revId; // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) { - (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? ffDetectNvidiaGpuInfo : ffDetectIntelGpuInfo)( + detectFn( &(FFGpuDriverCondition) { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID | FF_GPU_DRIVER_CONDITION_TYPE_LUID, .pciDeviceId = { @@ -107,18 +144,15 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .revId = revId, }, .luid = gpu->deviceId, - }, (FFGpuDriverResult) { + }, + (FFGpuDriverResult) { .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .type = &gpu->type, .frequency = &gpu->frequency, - }, gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA ? "nvml.dll" : - #ifdef _WIN64 - "ControlLib.dll" - #else - "ControlLib32.dll" - #endif + }, + dllName ); } } From a13520c5ff10640ed035ef2b21dfbf862fa42472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 21 Dec 2023 19:19:26 +0800 Subject: [PATCH 18/81] 3rdparty: remove unused types in `amd_ags` and make it complies in C Ref: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/issues/48 --- src/3rdparty/ags/amd_ags.h | 1016 +----------------------------------- src/3rdparty/ags/repo.json | 3 +- 2 files changed, 24 insertions(+), 995 deletions(-) diff --git a/src/3rdparty/ags/amd_ags.h b/src/3rdparty/ags/amd_ags.h index 7d23863a40..60b2dc7f6d 100644 --- a/src/3rdparty/ags/amd_ags.h +++ b/src/3rdparty/ags/amd_ags.h @@ -24,7 +24,7 @@ /// \mainpage /// AGS Library Overview /// -------------------- -/// This document provides an overview of the AGS (AMD GPU Services) library. The AGS library provides software developers with the ability to query +/// This document provides an overview of the AGS (AMD GPU Services) library. The AGS library provides software developers with the ability to query /// AMD GPU software and hardware state information that is not normally available through standard operating systems or graphic APIs. /// /// The latest version of the API is publicly hosted here: https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK/. @@ -99,8 +99,8 @@ /// * AGSSample /// * CrossfireSample /// * EyefinitySample -/// The AGSSample application is the simplest of the three examples and demonstrates the code required to initialize AGS and use it to query the GPU and Eyefinity state. -/// The CrossfireSample application demonstrates the use of the new API to transfer resources on GPUs in Crossfire mode. Lastly, the EyefinitySample application provides a more +/// The AGSSample application is the simplest of the three examples and demonstrates the code required to initialize AGS and use it to query the GPU and Eyefinity state. +/// The CrossfireSample application demonstrates the use of the new API to transfer resources on GPUs in Crossfire mode. Lastly, the EyefinitySample application provides a more /// extensive example of Eyefinity setup than the basic example provided in AGSSample. /// There are other samples on Github that demonstrate the DirectX shader extensions, such as the Barycentrics11 and Barycentrics12 samples. /// @@ -138,36 +138,6 @@ extern "C" { #define AGS_CURRENT_VERSION AGS_MAKE_VERSION( AMD_AGS_VERSION_MAJOR, AMD_AGS_VERSION_MINOR, AMD_AGS_VERSION_PATCH ) ///< Macro to return the current AGS version as defined by the AGS header file /// @} -#if !defined (AGS_DIRECTX_TYPES_INCLUDED) -// Forward declaration of D3D and DXGI types -struct IDXGIAdapter; -struct IDXGISwapChain; -struct DXGI_SWAP_CHAIN_DESC; -enum D3D_DRIVER_TYPE; -enum D3D_FEATURE_LEVEL; -enum D3D_PRIMITIVE_TOPOLOGY; - -// Forward declaration of D3D11 types -struct ID3D11Device; -struct ID3D11DeviceContext; -struct ID3D11Resource; -struct ID3D11Buffer; -struct ID3D11Texture1D; -struct ID3D11Texture2D; -struct ID3D11Texture3D; -struct D3D11_BUFFER_DESC; -struct D3D11_TEXTURE1D_DESC; -struct D3D11_TEXTURE2D_DESC; -struct D3D11_TEXTURE3D_DESC; -struct D3D11_SUBRESOURCE_DATA; -struct tagRECT; -typedef tagRECT D3D11_RECT; ///< typedef this ourselves so we don't have to drag d3d11.h in - -// Forward declaration of D3D12 types -struct ID3D12Device; -struct ID3D12GraphicsCommandList; -#endif - /// \defgroup enums General enumerations /// @{ @@ -189,7 +159,7 @@ typedef enum AGSReturnCode /// @} -struct AGSContext; ///< All function calls in AGS require a pointer to a context. This is generated via \ref agsInitialize +typedef struct AGSContext AGSContext; ///< All function calls in AGS require a pointer to a context. This is generated via \ref agsInitialize /// The rectangle struct used by AGS. typedef struct AGSRect @@ -252,26 +222,26 @@ typedef struct AGSDisplayInfo int reserved; ///< reserved field } AGSDisplayInfo; +/// The ASIC family +typedef enum AsicFamily +{ + AsicFamily_Unknown, ///< Unknown architecture, potentially from another IHV. Check \ref AGSDeviceInfo::vendorId + AsicFamily_PreGCN, ///< Pre GCN architecture. + AsicFamily_GCN1, ///< AMD GCN 1 architecture: Oland, Cape Verde, Pitcairn & Tahiti. + AsicFamily_GCN2, ///< AMD GCN 2 architecture: Hawaii & Bonaire. This also includes APUs Kaveri and Carrizo. + AsicFamily_GCN3, ///< AMD GCN 3 architecture: Tonga & Fiji. + AsicFamily_GCN4, ///< AMD GCN 4 architecture: Polaris. + AsicFamily_Vega, ///< AMD Vega architecture, including Raven Ridge (ie AMD Ryzen CPU + AMD Vega GPU). + AsicFamily_RDNA, ///< AMD RDNA architecture + AsicFamily_RDNA2, ///< AMD RDNA2 architecture + AsicFamily_RDNA3, ///< AMD RDNA3 architecture + + AsicFamily_Count ///< Number of enumerated ASIC families +} AsicFamily; + /// The device info struct used to describe a physical GPU enumerated by AGS typedef struct AGSDeviceInfo { - /// The ASIC family - typedef enum AsicFamily - { - AsicFamily_Unknown, ///< Unknown architecture, potentially from another IHV. Check \ref AGSDeviceInfo::vendorId - AsicFamily_PreGCN, ///< Pre GCN architecture. - AsicFamily_GCN1, ///< AMD GCN 1 architecture: Oland, Cape Verde, Pitcairn & Tahiti. - AsicFamily_GCN2, ///< AMD GCN 2 architecture: Hawaii & Bonaire. This also includes APUs Kaveri and Carrizo. - AsicFamily_GCN3, ///< AMD GCN 3 architecture: Tonga & Fiji. - AsicFamily_GCN4, ///< AMD GCN 4 architecture: Polaris. - AsicFamily_Vega, ///< AMD Vega architecture, including Raven Ridge (ie AMD Ryzen CPU + AMD Vega GPU). - AsicFamily_RDNA, ///< AMD RDNA architecture - AsicFamily_RDNA2, ///< AMD RDNA2 architecture - AsicFamily_RDNA3, ///< AMD RDNA3 architecture - - AsicFamily_Count ///< Number of enumerated ASIC families - } AsicFamily; - const char* adapterString; ///< The adapter name string AsicFamily asicFamily; ///< Set to Unknown if not AMD hardware unsigned int isAPU : 1; ///< Whether this device is an APU @@ -335,44 +305,7 @@ typedef struct AGSGPUInfo } AGSGPUInfo; /// The struct to specify the display settings to the driver. -typedef struct AGSDisplaySettings -{ - /// The display mode - typedef enum Mode - { - Mode_SDR, ///< SDR mode - Mode_HDR10_PQ, ///< HDR10 PQ encoding, requiring a 1010102 UNORM swapchain and PQ encoding in the output shader. - Mode_HDR10_scRGB, ///< HDR10 scRGB, requiring an FP16 swapchain. Values of 1.0 == 80 nits, 125.0 == 10000 nits. - Mode_FreesyncHDR_scRGB, ///< Freesync HDR scRGB, requiring an FP16 swapchain. A value of 1.0 == 80 nits. - Mode_FreesyncHDR_Gamma22, ///< Freesync HDR Gamma 2.2, requiring a 1010102 UNORM swapchain. The output needs to be encoded to gamma 2.2. - Mode_DolbyVision, ///< Dolby Vision, requiring an 8888 UNORM swapchain - - Mode_Count ///< Number of enumerated display modes - } Mode; - - Mode mode; ///< The display mode to set the display into - - double chromaticityRedX; ///< Red display primary X coord - double chromaticityRedY; ///< Red display primary Y coord - - double chromaticityGreenX; ///< Green display primary X coord - double chromaticityGreenY; ///< Green display primary Y coord - - double chromaticityBlueX; ///< Blue display primary X coord - double chromaticityBlueY; ///< Blue display primary Y coord - - double chromaticityWhitePointX; ///< White point X coord - double chromaticityWhitePointY; ///< White point Y coord - - double minLuminance; ///< The minimum scene luminance in nits - double maxLuminance; ///< The maximum scene luminance in nits - - double maxContentLightLevel; ///< The maximum content light level in nits (MaxCLL) - double maxFrameAverageLightLevel; ///< The maximum frame average light level in nits (MaxFALL) - - unsigned int disableLocalDimming : 1; ///< Disables local dimming if possible - unsigned int reservedPadding : 31; ///< Reserved -} AGSDisplaySettings; +typedef struct AGSDisplaySettings AGSDisplaySettings; /// The result returned from \ref agsCheckDriverVersion @@ -443,911 +376,6 @@ AMD_AGS_API AGSReturnCode agsSetDisplayMode( AGSContext* context, int deviceInde /// @} - -/// \defgroup dxappreg App Registration -/// @{ -/// This extension allows an application to voluntarily register itself with the driver, providing a more robust app detection solution and avoid the issue of the driver relying on exe names to match the app to a driver profile. -/// It is available when creating the device for both DirectX11 and DirectX12 via \ref agsDriverExtensionsDX11_CreateDevice and \ref agsDriverExtensionsDX12_CreateDevice respectively. -/// This feature is supported in Radeon Software Version 17.9.2 onwards. -/// Rules: -/// * AppName or EngineName must be set, but both are not required. Engine profiles will be used only if app specific profiles do not exist. -/// * In an engine, the EngineName should be set, so a default profile can be built. If an app modifies the engine, the AppName should be set, to allow a profile for the specific app. -/// * Version number is not mandatory, but recommended. The use of which can prevent the use of profiles for incompatible versions (for instance engine versions that introduce or change features), and can help prevent older profiles from being used (and introducing new bugs) before the profile is tested with new app builds. -/// * If Version numbers are used and a new version is introduced, a new profile will not be enabled until an AMD engineer has been able to update a previous profile, or make a new one. -/// -/// The cases for profile selection are as follows: -/// -/// |Case|Profile Applied| -/// |----|---------------| -/// | App or Engine Version has profile | The profile is used. | -/// | App or Engine Version num < profile version num | The closest profile > the version number is used. | -/// | App or Engine Version num > profile version num | No profile selected/The previous method is used. | -/// | App and Engine Version have profile | The App's profile is used. | -/// | App and Engine Version num < profile version | The closest App profile > the version number is used. | -/// | App and Engine Version, no App profile found | The Engine profile will be used. | -/// | App/Engine name but no Version, has profile | The latest profile is used. | -/// | No name or version, or no profile | The previous app detection method is used. | -/// -/// As shown above, if an App name is given, and a profile is found for that app, that will be prioritized. The Engine name and profile will be used only if no app name is given, or no viable profile is found for the app name. -/// In the case that App nor Engine have a profile, the previous app detection methods will be used. If given a version number that is larger than any profile version number, no profile will be selected. -/// This is specifically to prevent cases where an update to an engine or app will cause catastrophic breaks in the profile, allowing an engineer to test the profile before clearing it for public use with the new engine/app update. -/// -/// @} - -/// \defgroup dx12 DirectX12 Extensions -/// DirectX12 driver extensions -/// @{ - -/// \defgroup dx12init Device and device object creation and cleanup -/// It is now mandatory to call \ref agsDriverExtensionsDX12_CreateDevice when creating a device if the user wants to access any future DX12 AMD extensions. -/// The corresponding \ref agsDriverExtensionsDX12_DestroyDevice call must be called to release the device and free up the internal resources allocated by the create call. -/// @{ - -/// The struct to specify the DX12 device creation parameters -typedef struct AGSDX12DeviceCreationParams -{ - IDXGIAdapter* pAdapter; ///< Pointer to the adapter to use when creating the device. This may be null. - IID iid; ///< The interface ID for the type of device to be created. - D3D_FEATURE_LEVEL FeatureLevel; ///< The minimum feature level to create the device with. -} AGSDX12DeviceCreationParams; - -/// The struct to specify DX12 additional device creation parameters -typedef struct AGSDX12ExtensionParams -{ - const WCHAR* pAppName; ///< Application name - const WCHAR* pEngineName; ///< Engine name - unsigned int appVersion; ///< Application version - unsigned int engineVersion; ///< Engine version - unsigned int uavSlot; ///< The UAV slot reserved for intrinsic support. Refer to the \ref agsDriverExtensionsDX12_CreateDevice documentation for more details. -} AGSDX12ExtensionParams; - -/// The struct to hold all the returned parameters from the device creation call -typedef struct AGSDX12ReturnedParams -{ - ID3D12Device* pDevice; ///< The newly created device - typedef struct ExtensionsSupported /// Extensions for DX12 - { - unsigned int intrinsics16 : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. ReadFirstLane, ReadLane, LaneID, Swizzle, Ballot, MBCount, Med3, Barycentrics - unsigned int intrinsics17 : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. WaveReduce, WaveScan - unsigned int userMarkers : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. - unsigned int appRegistration : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. - unsigned int UAVBindSlot : 1; ///< Supported in Radeon Software Version 19.5.1 onwards. - unsigned int intrinsics19 : 1; ///< Supported in Radeon Software Version 19.12.2 onwards. DrawIndex, AtomicU64 - unsigned int baseVertex : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. - unsigned int baseInstance : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. - unsigned int getWaveSize : 1; ///< Supported in Radeon Software Version 20.5.1 onwards. - unsigned int floatConversion : 1; ///< Supported in Radeon Software Version 20.5.1 onwards. - unsigned int readLaneAt : 1; ///< Supported in Radeon Software Version 20.11.2 onwards. - unsigned int rayHitToken : 1; ///< Supported in Radeon Software Version 20.11.2 onwards. - unsigned int shaderClock : 1; ///< Supported in Radeon Software Version 23.1.1 onwards. - unsigned int padding : 19; ///< Reserved - } ExtensionsSupported; - ExtensionsSupported extensionsSupported; ///< List of supported extensions -} AGSDX12ReturnedParams; - -/// The space id for DirectX12 intrinsic support -const unsigned int AGS_DX12_SHADER_INTRINSICS_SPACE_ID = 0x7FFF0ADE; // 2147420894 - -/// -/// Function used to create a D3D12 device with additional AMD-specific initialization parameters. -/// -/// When using the HLSL shader extensions please note: -/// * The shader compiler should not use the D3DCOMPILE_SKIP_OPTIMIZATION (/Od) option or /O0, otherwise it will not work. -/// * The shader compiler needs D3DCOMPILE_ENABLE_STRICTNESS (/Ges) enabled. -/// * The intrinsic instructions require a 5.1 shader model. -/// * The Root Signature will need to reserve an extra UAV resource slot. This is not a real resource that requires allocating, it is just used to encode the intrinsic instructions. -/// -/// The easiest way to set up the reserved UAV slot is to specify it at u0. The register space id will automatically be assumed to be \ref AGS_DX12_SHADER_INTRINSICS_SPACE_ID. -/// The HLSL expects this as default and the set up code would look similar to this: -/// \code{.cpp} -/// CD3DX12_DESCRIPTOR_RANGE range[]; -/// ... -/// range[ 0 ].Init( D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0, AGS_DX12_SHADER_INTRINSICS_SPACE_ID ); // u0 at driver-reserved space id -/// \endcode -/// -/// Newer drivers also support a user-specified slot in which case the register space id is assumed to be 0. It is important that the \ref AGSDX12ReturnedParams::ExtensionsSupported::UAVBindSlot bit is set. -/// to ensure the driver can support this. If not, then u0 and \ref AGS_DX12_SHADER_INTRINSICS_SPACE_ID must be used. -/// If the driver does support this feature and a non zero slot is required, then the HLSL must also define AMD_EXT_SHADER_INTRINSIC_UAV_OVERRIDE as the matching slot value. -/// -/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize -/// \param [in] creationParams Pointer to the struct to specify the existing DX12 device creation parameters. -/// \param [in] extensionParams Optional pointer to the struct to specify DX12 additional device creation parameters. -/// \param [out] returnedParams Pointer to struct to hold all the returned parameters from the call. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_CreateDevice( AGSContext* context, const AGSDX12DeviceCreationParams* creationParams, const AGSDX12ExtensionParams* extensionParams, AGSDX12ReturnedParams* returnedParams ); - -/// -/// Function to destroy the D3D12 device. -/// This call will also cleanup any AMD-specific driver extensions for D3D12. -/// -/// \param [in] context Pointer to a context. -/// \param [in] device Pointer to the D3D12 device. -/// \param [out] deviceReferences Optional pointer to an unsigned int that will be set to the value returned from device->Release(). -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_DestroyDevice( AGSContext* context, ID3D12Device* device, unsigned int* deviceReferences ); - -/// @} - -/// \defgroup dx12usermarkers User Markers -/// @{ - -/// -/// Function used to push an AMD user marker onto the command list. -/// This is only has an effect if \ref AGSDX12ReturnedParams::ExtensionsSupported::userMarkers is present. -/// Supported in Radeon Software Version 17.9.1 onwards. -/// -/// \param [in] context Pointer to a context. -/// \param [in] commandList Pointer to the command list. -/// \param [in] data The UTF-8 marker string. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_PushMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList, const char* data ); - -/// -/// Function used to pop an AMD user marker on the command list. -/// Supported in Radeon Software Version 17.9.1 onwards. -/// -/// \param [in] context Pointer to a context. -/// \param [in] commandList Pointer to the command list. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_PopMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList ); - -/// -/// Function used to insert an single event AMD user marker onto the command list. -/// Supported in Radeon Software Version 17.9.1 onwards. -/// -/// \param [in] context Pointer to a context. -/// \param [in] commandList Pointer to the command list. -/// \param [in] data The UTF-8 marker string. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX12_SetMarker( AGSContext* context, ID3D12GraphicsCommandList* commandList, const char* data ); - -/// @} - -/// @} - -/// \defgroup dx11 DirectX11 Extensions -/// DirectX11 driver extensions -/// @{ - -/// \defgroup dx11init Device creation and cleanup -/// It is now mandatory to call \ref agsDriverExtensionsDX11_CreateDevice when creating a device if the user wants to access any DX11 AMD extensions. -/// The corresponding \ref agsDriverExtensionsDX11_DestroyDevice call must be called to release the device and free up the internal resources allocated by the create call. -/// @{ - -/// The different modes to control Crossfire behavior. -typedef enum AGSCrossfireMode -{ - AGS_CROSSFIRE_MODE_DRIVER_AFR = 0, ///< Use the default driver-based AFR rendering. If this mode is specified, do NOT use the agsDriverExtensionsDX11_Create*() APIs to create resources - AGS_CROSSFIRE_MODE_EXPLICIT_AFR, ///< Use the AGS Crossfire API functions to perform explicit AFR rendering without requiring a CF driver profile - AGS_CROSSFIRE_MODE_DISABLE ///< Completely disable AFR rendering -} AGSCrossfireMode; - -/// The struct to specify the existing DX11 device creation parameters -typedef struct AGSDX11DeviceCreationParams -{ - IDXGIAdapter* pAdapter; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - D3D_DRIVER_TYPE DriverType; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - HMODULE Software; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - UINT Flags; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - const D3D_FEATURE_LEVEL* pFeatureLevels; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - UINT FeatureLevels; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - UINT SDKVersion; ///< Consult the DX documentation on D3D11CreateDevice for this parameter - const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc; ///< Optional swapchain description. Specify this to invoke D3D11CreateDeviceAndSwapChain instead of D3D11CreateDevice. -} AGSDX11DeviceCreationParams; - -/// The struct to specify DX11 additional device creation parameters -typedef struct AGSDX11ExtensionParams -{ - const WCHAR* pAppName; ///< Application name - const WCHAR* pEngineName; ///< Engine name - unsigned int appVersion; ///< Application version - unsigned int engineVersion; ///< Engine version - unsigned int numBreadcrumbMarkers; ///< The number of breadcrumb markers to allocate. Each marker is a uint64 (ie 8 bytes). If 0, the system is disabled. - unsigned int uavSlot; ///< The UAV slot reserved for intrinsic support. This must match the slot defined in the HLSL, i.e. "#define AmdDxExtShaderIntrinsicsUAVSlot". - /// The default slot is 7, but the caller is free to use an alternative slot. - /// If 0 is specified, then the default of 7 will be used. - AGSCrossfireMode crossfireMode; ///< Desired Crossfire mode -} AGSDX11ExtensionParams; - -/// The struct to hold all the returned parameters from the device creation call -typedef struct AGSDX11ReturnedParams -{ - ID3D11Device* pDevice; ///< The newly created device - ID3D11DeviceContext* pImmediateContext; ///< The newly created immediate device context - IDXGISwapChain* pSwapChain; ///< The newly created swap chain. This is only created if a valid pSwapChainDesc is supplied in AGSDX11DeviceCreationParams. - D3D_FEATURE_LEVEL featureLevel; ///< The feature level supported by the newly created device - typedef struct ExtensionsSupported /// Extensions for DX11 - { - unsigned int quadList : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int screenRectList : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int uavOverlap : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int depthBoundsTest : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int multiDrawIndirect : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int multiDrawIndirectCountIndirect : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int crossfireAPI : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int createShaderControls : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. - unsigned int intrinsics16 : 1; ///< Supported in Radeon Software Version 16.9.2 onwards. ReadFirstLane, ReadLane, LaneID, Swizzle, Ballot, MBCount, Med3, Barycentrics - unsigned int multiView : 1; ///< Supported in Radeon Software Version 16.12.1 onwards. - unsigned int intrinsics17 : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. WaveReduce, WaveScan - unsigned int appRegistration : 1; ///< Supported in Radeon Software Version 17.9.1 onwards. - unsigned int breadcrumbMarkers : 1; ///< Supported in Radeon Software Version 17.11.1 onwards. - unsigned int MDIDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. - unsigned int UAVOverlapDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. - unsigned int depthBoundsDeferredContexts : 1; ///< Supported in Radeon Software Version 18.8.1 onwards. - unsigned int intrinsics19 : 1; ///< Supported in Radeon Software Version 19.12.2 onwards. DrawIndex, AtomicU64 - unsigned int getWaveSize : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. - unsigned int baseVertex : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. - unsigned int baseInstance : 1; ///< Supported in Radeon Software Version 20.2.1 onwards. - unsigned int padding : 12; ///< Reserved - } ExtensionsSupported; - ExtensionsSupported extensionsSupported; ///< List of supported extensions - unsigned int crossfireGPUCount; ///< The number of GPUs that are active for this app - void* breadcrumbBuffer; ///< The CPU buffer returned if the initialization of the breadcrumb was successful -} AGSDX11ReturnedParams; - -/// -/// Function used to create a D3D11 device with additional AMD-specific initialization parameters. -/// -/// When using the HLSL shader extensions please note: -/// * The shader compiler should not use the D3DCOMPILE_SKIP_OPTIMIZATION (/Od) option, otherwise it will not work. -/// * The shader compiler needs D3DCOMPILE_ENABLE_STRICTNESS (/Ges) enabled. -/// -/// \param [in] context Pointer to a context. This is generated by \ref agsInitialize -/// \param [in] creationParams Pointer to the struct to specify the existing DX11 device creation parameters. -/// \param [in] extensionParams Optional pointer to the struct to specify DX11 additional device creation parameters. -/// \param [out] returnedParams Pointer to struct to hold all the returned parameters from the call. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateDevice( AGSContext* context, const AGSDX11DeviceCreationParams* creationParams, const AGSDX11ExtensionParams* extensionParams, AGSDX11ReturnedParams* returnedParams ); - -/// -/// Function to destroy the D3D11 device and its immediate context. -/// This call will also cleanup any AMD-specific driver extensions for D3D11. -/// -/// \param [in] context Pointer to a context. -/// \param [in] device Pointer to the D3D11 device. -/// \param [out] deviceReferences Optional pointer to an unsigned int that will be set to the value returned from device->Release(). -/// \param [in] immediateContext Pointer to the D3D11 immediate device context. -/// \param [out] immediateContextReferences Optional pointer to an unsigned int that will be set to the value returned from immediateContext->Release(). -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_DestroyDevice( AGSContext* context, ID3D11Device* device, unsigned int* deviceReferences, ID3D11DeviceContext* immediateContext, unsigned int* immediateContextReferences ); - -/// @} - -/// \defgroup breadcrumbs Breadcrumb API -/// API for writing top-of-pipe and bottom-of-pipe markers to help track down GPU hangs. -/// -/// The API is available if the \ref AGSDX11ReturnedParams::ExtensionsSupported::breadcrumbMarkers is present. -/// -/// To use the API, a non zero value needs to be specificed in \ref AGSDX11ExtensionParams::numBreadcrumbMarkers. This enables the API (if available) and allocates a system memory buffer -/// which is returned to the user in \ref AGSDX11ReturnedParams::breadcrumbBuffer. -/// -/// The user can now write markers before and after draw calls using \ref agsDriverExtensionsDX11_WriteBreadcrumb. -/// -/// \section background Background -/// -/// A top-of-pipe (TOP) command is scheduled for execution as soon as the command processor (CP) reaches the command. -/// A bottom-of-pipe (BOP) command is scheduled for execution once the previous rendering commands (draw and dispatch) finish execution. -/// TOP and BOP commands do not block CP. i.e. the CP schedules the command for execution then proceeds to the next command without waiting. -/// To effectively use TOP and BOP commands, it is important to understand how they interact with rendering commands: -/// -/// When the CP encounters a rendering command it queues it for execution and moves to the next command. The queued rendering commands are issued in order. -/// There can be multiple rendering commands running in parallel. When a rendering command is issued we say it is at the top of the pipe. When a rendering command -/// finishes execution we say it has reached the bottom of the pipe. -/// -/// A BOP command remains in a waiting queue and is executed once prior rendering commands finish. The queue of BOP commands is limited to 64 entries in GCN generation 1, 2, 3, 4 and 5. -/// If the 64 limit is reached the CP will stop queueing BOP commands and also rendering commands. Developers should limit the number of BOP commands that write markers to avoid contention. -/// In general, developers should limit both TOP and BOP commands to avoid stalling the CP. -/// -/// \subsection eg1 Example 1: -/// -/// \code{.cpp} -/// // Start of a command buffer -/// WriteMarker(TopOfPipe, 1) -/// WriteMarker(BottomOfPipe, 2) -/// WriteMarker(BottomOfPipe, 3) -/// DrawX -/// WriteMarker(BottomOfPipe, 4) -/// WriteMarker(BottomOfPipe, 5) -/// WriteMarker(TopOfPipe, 6) -/// // End of command buffer -/// \endcode -/// -/// In the above example, the CP writes markers 1, 2 and 3 without waiting: -/// Marker 1 is TOP so it's independent from other commands -/// There's no wait for marker 2 and 3 because there are no draws preceding the BOP commands -/// Marker 4 is only written once DrawX finishes execution -/// Marker 5 doesn't wait for additional draws so it is written right after marker 4 -/// Marker 6 can be written as soon as the CP reaches the command. For instance, it is very possible that CP writes marker 6 while DrawX -/// is running and therefore marker 6 gets written before markers 4 and 5 -/// -/// \subsection eg2 Example 2: -/// -/// \code{.cpp} -/// WriteMarker(TopOfPipe, 1) -/// DrawX -/// WriteMarker(BottomOfPipe, 2) -/// WriteMarker(TopOfPipe, 3) -/// DrawY -/// WriteMarker(BottomOfPipe, 4) -/// \endcode -/// -/// In this example marker 1 is written before the start of DrawX -/// Marker 2 is written once DrawX finishes execution -/// Similarly marker 3 is written before the start of DrawY -/// Marker 4 is written once DrawY finishes execution -/// In case of a GPU hang, if markers 1 and 3 are written but markers 2 and 4 are missing we can conclude that: -/// The CP has reached both DrawX and DrawY commands since marker 1 and 3 are present -/// The fact that marker 2 and 4 are missing means that either DrawX is hanging while DrawY is at the top of the pipe or both DrawX and DrawY -/// started and both are simultaneously hanging -/// -/// \subsection eg3 Example 3: -/// -/// \code{.cpp} -/// // Start of a command buffer -/// WriteMarker(BottomOfPipe, 1) -/// DrawX -/// WriteMarker(BottomOfPipe, 2) -/// DrawY -/// WriteMarker(BottomOfPipe, 3) -/// DrawZ -/// WriteMarker(BottomOfPipe, 4) -/// // End of command buffer -/// \endcode -/// -/// In this example marker 1 is written before the start of DrawX -/// Marker 2 is written once DrawX finishes -/// Marker 3 is written once DrawY finishes -/// Marker 4 is written once DrawZ finishes -/// If the GPU hangs and only marker 1 is written we can conclude that the hang is happening in either DrawX, DrawY or DrawZ -/// If the GPU hangs and only marker 1 and 2 are written we can conclude that the hang is happening in DrawY or DrawZ -/// If the GPU hangs and only marker 4 is missing we can conclude that the hang is happening in DrawZ -/// -/// \subsection eg4 Example 4: -/// -/// \code{.cpp} -/// Start of a command buffer -/// WriteMarker(TopOfPipe, 1) -/// DrawX -/// WriteMarker(TopOfPipe, 2) -/// DrawY -/// WriteMarker(TopOfPipe, 3) -/// DrawZ -/// // End of command buffer -/// \endcode -/// -/// In this example, in case the GPU hangs and only marker 1 is written we can conclude that the hang is happening in DrawX -/// In case the GPU hangs and only marker 1 and 2 are written we can conclude that the hang is happening in DrawX or DrawY -/// In case the GPU hangs and all 3 markers are written we can conclude that the hang is happening in any of DrawX, DrawY or DrawZ -/// -/// \subsection eg5 Example 5: -/// -/// \code{.cpp} -/// DrawX -/// WriteMarker(TopOfPipe, 1) -/// WriteMarker(BottomOfPipe, 2) -/// DrawY -/// WriteMarker(TopOfPipe, 3) -/// WriteMarker(BottomOfPipe, 4) -/// \endcode -/// -/// Marker 1 is written right after DrawX is queued for execution. -/// Marker 2 is only written once DrawX finishes execution. -/// Marker 3 is written right after DrawY is queued for execution. -/// Marker 4 is only written once DrawY finishes execution -/// If marker 1 is written we would know that the CP has reached the command DrawX (DrawX at the top of the pipe). -/// If marker 2 is written we can say that DrawX has finished execution (DrawX at the bottom of the pipe). -/// In case the GPU hangs and only marker 1 and 3 are written we can conclude that the hang is happening in DrawX or DrawY -/// In case the GPU hangs and only marker 1 is written we can conclude that the hang is happening in DrawX -/// In case the GPU hangs and only marker 4 is missing we can conclude that the hang is happening in DrawY -/// -/// \section data Retrieving GPU Data -/// -/// In the event of a GPU hang, the user can inspect the system memory buffer to determine which draw has caused the hang. -/// For example: -/// \code{.cpp} -/// // Force the work to be flushed to prevent CPU ahead of GPU -/// g_pImmediateContext->Flush(); -/// -/// // Present the information rendered to the back buffer to the front buffer (the screen) -/// HRESULT hr = g_pSwapChain->Present( 0, 0 ); -/// -/// // Read the marker data buffer once detect device lost -/// if ( hr != S_OK ) -/// { -/// for (UINT i = 0; i < g_NumMarkerWritten; i++) -/// { -/// UINT64* pTempData; -/// pTempData = static_cast(pMarkerBuffer); -/// -/// // Write the marker data to file -/// ofs << i << "\r\n"; -/// ofs << std::hex << *(pTempData + i * 2) << "\r\n"; -/// ofs << std::hex << *(pTempData + (i * 2 + 1)) << "\r\n"; -/// -/// WCHAR s1[256]; -/// setlocale(LC_NUMERIC, "en_US.iso88591"); -/// -/// // Output the marker data to console -/// swprintf(s1, 256, L" The Draw count is %d; The Top maker is % 016llX and the Bottom marker is % 016llX \r\n", i, *(pTempData + i * 2), *(pTempData + (i * 2 + 1))); -/// -/// OutputDebugStringW(s1); -/// } -/// } -/// \endcode -/// -/// The console output would resemble something like: -/// \code{.cpp} -/// D3D11: Removing Device. -/// D3D11 ERROR: ID3D11Device::RemoveDevice: Device removal has been triggered for the following reason (DXGI_ERROR_DEVICE_HUNG: The Device took an unreasonable amount of time to execute its commands, or the hardware crashed/hung. As a result, the TDR (Timeout Detection and Recovery) mechanism has been triggered. The current Device Context was executing commands when the hang occurred. The application may want to respawn and fallback to less aggressive use of the display hardware). [ EXECUTION ERROR #378: DEVICE_REMOVAL_PROCESS_AT_FAULT] -/// The Draw count is 0; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF -/// The Draw count is 1; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF -/// The Draw count is 2; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF -/// The Draw count is 3; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF -/// The Draw count is 4; The Top maker is 00000000DEADCAFE and the Bottom marker is 00000000DEADBEEF -/// The Draw count is 5; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD -/// The Draw count is 6; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD -/// The Draw count is 7; The Top maker is CDCDCDCDCDCDCDCD and the Bottom marker is CDCDCDCDCDCDCDCD -/// \endcode -/// -/// @{ - -/// The breadcrumb marker struct used by \ref agsDriverExtensionsDX11_WriteBreadcrumb -typedef struct AGSBreadcrumbMarker -{ - /// The marker type - typedef enum Type - { - TopOfPipe = 0, ///< Top-of-pipe marker - BottomOfPipe = 1 ///< Bottom-of-pipe marker - } Type; - - unsigned long long markerData; ///< The user data to write. - Type type; ///< Whether this marker is top or bottom of pipe. - unsigned int index; ///< The index of the marker. This should be less than the value specified in \ref AGSDX11ExtensionParams::numBreadcrumbMarkers -} AGSBreadcrumbMarker; - -/// -/// Function to write a breadcrumb marker. -/// -/// This method inserts a write marker operation in the GPU command stream. In the case where the GPU is hanging the write -/// command will never be reached and the marker will never get written to memory. -/// -/// In order to use this function, \ref AGSDX11ExtensionParams::numBreadcrumbMarkers must be set to a non zero value. -/// -/// \param [in] context Pointer to a context. -/// \param [in] marker Pointer to a marker. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_WriteBreadcrumb( AGSContext* context, const AGSBreadcrumbMarker* marker ); - -/// @} - -/// \defgroup dx11Topology Extended Topology -/// API for primitive topologies -/// @{ - -/// Additional topologies supported via extensions -typedef enum AGSPrimitiveTopologyDX11 -{ - AGS_PRIMITIVE_TOPOLOGY_QUADLIST = 7, ///< Quad list - AGS_PRIMITIVE_TOPOLOGY_SCREENRECTLIST = 9 ///< Screen rect list -} AGSPrimitiveTopologyDX11; - -/// -/// Function used to set the primitive topology. If you are using any of the extended topology types, then this function should -/// be called to set ALL topology types. -/// -/// The Quad List extension is a convenient way to submit quads without using an index buffer. Note that this still submits two triangles at the driver level. -/// In order to use this function, AGS must already be initialized and agsDriverExtensionsDX11_Init must have been called successfully. -/// -/// The Screen Rect extension, which is only available on GCN hardware, allows the user to pass in three of the four corners of a rectangle. -/// The hardware then uses the bounding box of the vertices to rasterize the rectangle primitive (i.e. as a rectangle rather than two triangles). -/// \note Note that this will not return valid interpolated values, only valid SV_Position values. -/// \note If either the Quad List or Screen Rect extension are used, then agsDriverExtensionsDX11_IASetPrimitiveTopology should be called in place of the native DirectX11 equivalent all the time. -/// -/// \param [in] context Pointer to a context. -/// \param [in] topology The topology to set on the D3D11 device. This can be either an AGS-defined topology such as AGS_PRIMITIVE_TOPOLOGY_QUADLIST -/// or a standard D3D-defined topology such as D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP. -/// NB. the AGS-defined types will require casting to a D3D_PRIMITIVE_TOPOLOGY type. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_IASetPrimitiveTopology( AGSContext* context, D3D_PRIMITIVE_TOPOLOGY topology ); - -/// @} - -/// \defgroup dx11UAVOverlap UAV Overlap -/// API for enabling overlapping UAV writes -/// -/// The AMD DX11 driver will automatically track resource usage and insert barriers as necessary to clear read-after-write (RAW) and write-after-write (WAW) -/// hazards. The UAV overlap extension allows applications to indicate to the driver it can skip inserting barriers for UAV resources used in -/// dispatches and draws within the \ref agsDriverExtensionsDX11_BeginUAVOverlap/ \ref agsDriverExtensionsDX11_EndUAVOverlap calls. This can be useful for applications to allow -/// multiple back-to-back dispatches or draws in flight even if they are accessing the same UAV resource but the data written or read does not overlap within the resource. -/// -/// Usage would be as follows: -/// \code{.cpp} -/// m_device->Dispatch( ... ); // First call that writes to the UAV -/// -/// // Disable automatic WAW syncs -/// agsDriverExtensionsDX11_BeginUAVOverlap( m_agsContext ); -/// -/// // Submit other dispatches that write to the same UAV concurrently -/// m_device->Dispatch( ... ); -/// m_device->Dispatch( ... ); -/// m_device->Dispatch( ... ); -/// -/// // Reenable automatic WAW syncs -/// agsDriverExtensionsDX11_EndUAVOverlap( m_agsContext ); -/// \endcode -/// @{ - -/// -/// Function used indicate to the driver the start of the overlap scope. -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// with the AGS_DX11_EXTENSION_DEFERRED_CONTEXTS bit. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_BeginUAVOverlap( AGSContext* context, ID3D11DeviceContext* dxContext ); - -/// -/// Function used indicate to the driver the end of the overlap scope. -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// with the AGS_DX11_EXTENSION_DEFERRED_CONTEXTS bit. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_EndUAVOverlap( AGSContext* context, ID3D11DeviceContext* dxContext ); - -/// @} - -/// \defgroup dx11DepthBoundsTest Depth Bounds Test -/// API for enabling depth bounds testing -/// @{ - -/// -/// Function used to set the depth bounds test extension -/// -/// \param [in] context Pointer to a context -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// \param [in] enabled Whether to enable or disable the depth bounds testing. If disabled, the next two args are ignored. -/// \param [in] minDepth The near depth range to clip against. -/// \param [in] maxDepth The far depth range to clip against. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetDepthBounds( AGSContext* context, ID3D11DeviceContext* dxContext, bool enabled, float minDepth, float maxDepth ); - -/// @} - -/// \defgroup mdi Multi Draw Indirect (MDI) -/// API for dispatching multiple instanced draw commands. -/// The multi draw indirect extensions allow multiple sets of DrawInstancedIndirect to be submitted in one API call. -/// The draw calls are issued on the GPU's command processor (CP), potentially saving the significant CPU overheads incurred by submitting the equivalent draw calls on the CPU. -/// -/// The extension allows the following code: -/// \code{.cpp} -/// // Submit n batches of DrawIndirect calls -/// for ( int i = 0; i < n; i++ ) -/// deviceContext->DrawIndexedInstancedIndirect( buffer, i * sizeof( cmd ) ); -/// \endcode -/// To be replaced by the following call: -/// \code{.cpp} -/// // Submit all n batches in one call -/// agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect( m_agsContext, deviceContext, n, buffer, 0, sizeof( cmd ) ); -/// \endcode -/// -/// The buffer used for the indirect args must be of the following formats: -/// \code{.cpp} -/// // Buffer layout for agsDriverExtensions_MultiDrawInstancedIndirect -/// struct DrawInstancedIndirectArgs -/// { -/// UINT VertexCountPerInstance; -/// UINT InstanceCount; -/// UINT StartVertexLocation; -/// UINT StartInstanceLocation; -/// }; -/// -/// // Buffer layout for agsDriverExtensions_MultiDrawIndexedInstancedIndirect -/// struct DrawIndexedInstancedIndirectArgs -/// { -/// UINT IndexCountPerInstance; -/// UINT InstanceCount; -/// UINT StartIndexLocation; -/// UINT BaseVertexLocation; -/// UINT StartInstanceLocation; -/// }; -/// \endcode -/// -/// Example usage can be seen in AMD's GeometryFX (https://github.com/GPUOpen-Effects/GeometryFX). In particular, in this file: https://github.com/GPUOpen-Effects/GeometryFX/blob/master/amd_geometryfx/src/AMD_GeometryFX_Filtering.cpp -/// -/// @{ - -/// -/// Function used to submit a batch of draws via MultiDrawIndirect -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// \param [in] drawCount The number of draws. -/// \param [in] pBufferForArgs The args buffer. -/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. -/// \param [in] byteStrideForArgs The per element stride of the args buffer. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawInstancedIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, unsigned int drawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); - -/// -/// Function used to submit a batch of draws via MultiDrawIndirect -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// \param [in] drawCount The number of draws. -/// \param [in] pBufferForArgs The args buffer. -/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. -/// \param [in] byteStrideForArgs The per element stride of the args buffer. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, unsigned int drawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); - -/// -/// Function used to submit a batch of draws via MultiDrawIndirect -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// \param [in] pBufferForDrawCount The draw count buffer. -/// \param [in] alignedByteOffsetForDrawCount The offset into the draw count buffer. -/// \param [in] pBufferForArgs The args buffer. -/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. -/// \param [in] byteStrideForArgs The per element stride of the args buffer. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawInstancedIndirectCountIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, ID3D11Buffer* pBufferForDrawCount, unsigned int alignedByteOffsetForDrawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); - -/// -/// Function used to submit a batch of draws via MultiDrawIndirect -/// -/// \param [in] context Pointer to a context. -/// \param [in] dxContext Pointer to the DirectX device context. If this is to work using the non-immediate context, then you need to check support. If nullptr is specified, then the immediate context is assumed. -/// \param [in] pBufferForDrawCount The draw count buffer. -/// \param [in] alignedByteOffsetForDrawCount The offset into the draw count buffer. -/// \param [in] pBufferForArgs The args buffer. -/// \param [in] alignedByteOffsetForArgs The offset into the args buffer. -/// \param [in] byteStrideForArgs The per element stride of the args buffer. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirectCountIndirect( AGSContext* context, ID3D11DeviceContext* dxContext, ID3D11Buffer* pBufferForDrawCount, unsigned int alignedByteOffsetForDrawCount, ID3D11Buffer* pBufferForArgs, unsigned int alignedByteOffsetForArgs, unsigned int byteStrideForArgs ); - -/// @} - -/// \defgroup shadercompiler Shader Compiler Controls -/// API for controlling DirectX11 shader compilation. -/// Check support for this feature using the AGS_DX11_EXTENSION_CREATE_SHADER_CONTROLS bit. -/// Supported in Radeon Software Version 16.9.2 (driver version 16.40.2311) onwards. -/// @{ - -/// -/// This method can be used to limit the maximum number of threads the driver uses for asynchronous shader compilation. -/// Setting it to 0 will disable asynchronous compilation completely and force the shaders to be compiled "inline" on the threads that call Create*Shader. -/// -/// This method can only be called before any shaders are created and being compiled by the driver. -/// If this method is called after shaders have been created the function will return AGS_FAILURE. -/// This function only sets an upper limit.The driver may create fewer threads than allowed by this function. -/// -/// \param [in] context Pointer to a context. -/// \param [in] numberOfThreads The maximum number of threads to use. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetMaxAsyncCompileThreadCount( AGSContext* context, unsigned int numberOfThreads ); - -/// -/// This method can be used to determine the total number of asynchronous shader compile jobs that are either -/// queued for waiting for compilation or being compiled by the driver's asynchronous compilation threads. -/// This method can be called at any during the lifetime of the driver. -/// -/// \param [in] context Pointer to a context. -/// \param [out] numberOfJobs Pointer to the number of jobs in flight currently. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NumPendingAsyncCompileJobs( AGSContext* context, unsigned int* numberOfJobs ); - -/// -/// This method can be used to enable or disable the disk based shader cache. -/// Enabling/disabling the disk cache is not supported if is it disabled explicitly via Radeon Settings or by an app profile. -/// Calling this method under these conditions will result in AGS_FAILURE being returned. -/// It is recommended that this method be called before any shaders are created by the application and being compiled by the driver. -/// Doing so at any other time may result in the cache being left in an inconsistent state. -/// -/// \param [in] context Pointer to a context. -/// \param [in] enable Whether to enable the disk cache. 0 to disable, 1 to enable. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetDiskShaderCacheEnabled( AGSContext* context, int enable ); - -/// @} - -/// \defgroup multiview Multiview -/// API for multiview broadcasting. -/// Check support for this feature using the AGS_DX11_EXTENSION_MULTIVIEW bit. -/// Supported in Radeon Software Version 16.12.1 (driver version 16.50.2001) onwards. -/// @{ - -/// -/// Function to control draw calls replication to multiple viewports and RT slices. -/// Setting any mask to 0 disables draw replication. -/// -/// \param [in] context Pointer to a context. -/// \param [in] vpMask Viewport control bit mask. -/// \param [in] rtSliceMask RT slice control bit mask. -/// \param [in] vpMaskPerRtSliceEnabled If 0, 16 lower bits of vpMask apply to all RT slices; if 1 each 16 bits of 64-bit mask apply to corresponding 4 RT slices. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetViewBroadcastMasks( AGSContext* context, unsigned long long vpMask, unsigned long long rtSliceMask, int vpMaskPerRtSliceEnabled ); - -/// -/// Function returns max number of supported clip rectangles. -/// -/// \param [in] context Pointer to a context. -/// \param [out] maxRectCount Returned max number of clip rectangles. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_GetMaxClipRects( AGSContext* context, unsigned int* maxRectCount ); - -/// The clip rectangle struct used by \ref agsDriverExtensionsDX11_SetClipRects -typedef struct AGSClipRect -{ - /// The inclusion mode for the rect - typedef enum Mode - { - ClipRectIncluded = 0, ///< Include the rect - ClipRectExcluded = 1 ///< Exclude the rect - } Mode; - - Mode mode; ///< Include/exclude rect region - AGSRect rect; ///< The rect to include/exclude -} AGSClipRect; - -/// -/// Function sets clip rectangles. -/// -/// \param [in] context Pointer to a context. -/// \param [in] clipRectCount Number of specified clip rectangles. Use 0 to disable clip rectangles. -/// \param [in] clipRects Array of clip rectangles. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_SetClipRects( AGSContext* context, unsigned int clipRectCount, const AGSClipRect* clipRects ); - -/// @} - -/// \defgroup cfxapi Explicit Crossfire API -/// API for explicit control over Crossfire -/// @{ - -/// The Crossfire API transfer types -typedef enum AGSAfrTransferType -{ - AGS_AFR_TRANSFER_DEFAULT = 0, ///< Default Crossfire driver resource tracking - AGS_AFR_TRANSFER_DISABLE = 1, ///< Turn off driver resource tracking - AGS_AFR_TRANSFER_1STEP_P2P = 2, ///< App controlled GPU to next GPU transfer - AGS_AFR_TRANSFER_2STEP_NO_BROADCAST = 3, ///< App controlled GPU to next GPU transfer using intermediate system memory - AGS_AFR_TRANSFER_2STEP_WITH_BROADCAST = 4, ///< App controlled GPU to all render GPUs transfer using intermediate system memory -} AGSAfrTransferType; - -/// The Crossfire API transfer engines -typedef enum AGSAfrTransferEngine -{ - AGS_AFR_TRANSFERENGINE_DEFAULT = 0, ///< Use default engine for Crossfire API transfers - AGS_AFR_TRANSFERENGINE_3D_ENGINE = 1, ///< Use 3D engine for Crossfire API transfers - AGS_AFR_TRANSFERENGINE_COPY_ENGINE = 2, ///< Use Copy engine for Crossfire API transfers -} AGSAfrTransferEngine; - -/// -/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. -/// -/// \param [in] context Pointer to a context. -/// \param [in] desc Pointer to the D3D11 resource description. -/// \param [in] initialData Optional pointer to the initializing data for the resource. -/// \param [out] buffer Returned pointer to the resource. -/// \param [in] transferType The transfer behavior. -/// \param [in] transferEngine The transfer engine to use. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateBuffer( AGSContext* context, const D3D11_BUFFER_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Buffer** buffer, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); - -/// -/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. -/// -/// \param [in] context Pointer to a context. -/// \param [in] desc Pointer to the D3D11 resource description. -/// \param [in] initialData Optional pointer to the initializing data for the resource. -/// \param [out] texture1D Returned pointer to the resource. -/// \param [in] transferType The transfer behavior. -/// \param [in] transferEngine The transfer engine to use. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture1D( AGSContext* context, const D3D11_TEXTURE1D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture1D** texture1D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); - -/// -/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. -/// -/// \param [in] context Pointer to a context. -/// \param [in] desc Pointer to the D3D11 resource description. -/// \param [in] initialData Optional pointer to the initializing data for the resource. -/// \param [out] texture2D Returned pointer to the resource. -/// \param [in] transferType The transfer behavior. -/// \param [in] transferEngine The transfer engine to use. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture2D( AGSContext* context, const D3D11_TEXTURE2D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture2D** texture2D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); - -/// -/// Function to create a Direct3D11 resource with the specified AFR transfer type and specified transfer engine. -/// -/// \param [in] context Pointer to a context. -/// \param [in] desc Pointer to the D3D11 resource description. -/// \param [in] initialData Optional pointer to the initializing data for the resource. -/// \param [out] texture3D Returned pointer to the resource. -/// \param [in] transferType The transfer behavior. -/// \param [in] transferEngine The transfer engine to use. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_CreateTexture3D( AGSContext* context, const D3D11_TEXTURE3D_DESC* desc, const D3D11_SUBRESOURCE_DATA* initialData, ID3D11Texture3D** texture3D, AGSAfrTransferType transferType, AGSAfrTransferEngine transferEngine ); - -/// -/// Function to notify the driver that we have finished writing to the resource this frame. -/// This will initiate a transfer for AGS_AFR_TRANSFER_1STEP_P2P, -/// AGS_AFR_TRANSFER_2STEP_NO_BROADCAST, and AGS_AFR_TRANSFER_2STEP_WITH_BROADCAST. -/// -/// \param [in] context Pointer to a context. -/// \param [in] resource Pointer to the resource. -/// \param [in] transferRegions An array of transfer regions (can be null to specify the whole area). -/// \param [in] subresourceArray An array of subresource indices (can be null to specify all subresources). -/// \param [in] numSubresources The number of subresources in subresourceArray OR number of transferRegions. Use 0 to specify ALL subresources and one transferRegion (which may be null if specifying the whole area). -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceEndWrites( AGSContext* context, ID3D11Resource* resource, const D3D11_RECT* transferRegions, const unsigned int* subresourceArray, unsigned int numSubresources ); - -/// -/// This will notify the driver that the app will begin read/write access to the resource. -/// -/// \param [in] context Pointer to a context. -/// \param [in] resource Pointer to the resource. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceBeginAllAccess( AGSContext* context, ID3D11Resource* resource ); - -/// -/// This is used for AGS_AFR_TRANSFER_1STEP_P2P to notify when it is safe to initiate a transfer. -/// This call in frame N-(NumGpus-1) allows a 1 step P2P in frame N to start. -/// This should be called after agsDriverExtensionsDX11_NotifyResourceEndWrites. -/// -/// \param [in] context Pointer to a context. -/// \param [in] resource Pointer to the resource. -/// -AMD_AGS_API AGSReturnCode agsDriverExtensionsDX11_NotifyResourceEndAllAccess( AGSContext* context, ID3D11Resource* resource ); - -/// @} - -/// @} - -/// \defgroup typedefs Function pointer typedefs -/// List of function pointer typedefs for the API -/// @{ - -typedef AMD_AGS_API AGSDriverVersionResult (*AGS_CHECKDRIVERVERSION)( const char*, unsigned int ); ///< \ref agsCheckDriverVersion -typedef AMD_AGS_API int (*AGS_GETVERSIONNUMBER)(); ///< \ref agsGetVersionNumber -typedef AMD_AGS_API AGSReturnCode (*AGS_INITIALIZE)( int, const AGSConfiguration*, AGSContext**, AGSGPUInfo* ); ///< \ref agsInitialize -typedef AMD_AGS_API AGSReturnCode (*AGS_DEINITIALIZE)( AGSContext* ); ///< \ref agsDeInitialize -typedef AMD_AGS_API AGSReturnCode (*AGS_SETDISPLAYMODE)( AGSContext*, int, int, const AGSDisplaySettings* ); ///< \ref agsSetDisplayMode -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_CREATEDEVICE)( AGSContext*, const AGSDX12DeviceCreationParams*, const AGSDX12ExtensionParams*, AGSDX12ReturnedParams* ); ///< \ref agsDriverExtensionsDX12_CreateDevice -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_DESTROYDEVICE)( AGSContext*, ID3D12Device*, unsigned int* ); ///< \ref agsDriverExtensionsDX12_DestroyDevice -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_PUSHMARKER)( AGSContext*, ID3D12GraphicsCommandList*, const char* ); ///< \ref agsDriverExtensionsDX12_PushMarker -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_POPMARKER)( AGSContext*, ID3D12GraphicsCommandList* ); ///< \ref agsDriverExtensionsDX12_PopMarker -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX12_SETMARKER)( AGSContext*, ID3D12GraphicsCommandList*, const char* ); ///< \ref agsDriverExtensionsDX12_SetMarker -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATEDEVICE)( AGSContext*, const AGSDX11DeviceCreationParams*, const AGSDX11ExtensionParams*, AGSDX11ReturnedParams* ); ///< \ref agsDriverExtensionsDX11_CreateDevice -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_DESTROYDEVICE)( AGSContext*, ID3D11Device*, unsigned int*, ID3D11DeviceContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_DestroyDevice -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_WRITEBREADCRUMB)( AGSContext*, const AGSBreadcrumbMarker* ); ///< \ref agsDriverExtensionsDX11_WriteBreadcrumb -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_IASETPRIMITIVETOPOLOGY)( AGSContext*, enum D3D_PRIMITIVE_TOPOLOGY ); ///< \ref agsDriverExtensionsDX11_IASetPrimitiveTopology -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_BEGINUAVOVERLAP)( AGSContext*, ID3D11DeviceContext* ); ///< \ref agsDriverExtensionsDX11_BeginUAVOverlap -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_ENDUAVOVERLAP)( AGSContext*, ID3D11DeviceContext* ); ///< \ref agsDriverExtensionsDX11_EndUAVOverlap -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETDEPTHBOUNDS)( AGSContext*, ID3D11DeviceContext*, bool, float, float ); ///< \ref agsDriverExtensionsDX11_SetDepthBounds -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINSTANCEDINDIRECT)( AGSContext*, ID3D11DeviceContext*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawInstancedIndirect -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINDEXEDINSTANCEDINDIRECT)( AGSContext*, ID3D11DeviceContext*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirect -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINSTANCEDINDIRECTCOUNTINDIRECT)( AGSContext*, ID3D11DeviceContext*, ID3D11Buffer*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawInstancedIndirectCountIndirect -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_MULTIDRAWINDEXEDINSTANCEDINDIRECTCOUNTINDIRECT)( AGSContext*, ID3D11DeviceContext*, ID3D11Buffer*, unsigned int, ID3D11Buffer*, unsigned int, unsigned int ); ///< \ref agsDriverExtensionsDX11_MultiDrawIndexedInstancedIndirectCountIndirect -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETMAXASYNCCOMPILETHREADCOUNT)( AGSContext*, unsigned int ); ///< \ref agsDriverExtensionsDX11_SetMaxAsyncCompileThreadCount -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NUMPENDINGASYNCOMPILEJOBS)( AGSContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_NumPendingAsyncCompileJobs -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETDISKSHADERCACHEENABLED)( AGSContext*, int ); ///< \ref agsDriverExtensionsDX11_SetDiskShaderCacheEnabled -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETVIEWBROADCASTMASKS)( AGSContext*, unsigned long long, unsigned long long, int ); ///< \ref agsDriverExtensionsDX11_SetViewBroadcastMasks -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_GETMAXCLIPRECTS)( AGSContext*, unsigned int* ); ///< \ref agsDriverExtensionsDX11_GetMaxClipRects -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_SETCLIPRECTS)( AGSContext*, unsigned int, const AGSClipRect* ); ///< \ref agsDriverExtensionsDX11_SetClipRects -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATEBUFFER)( AGSContext*, const D3D11_BUFFER_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Buffer**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateBuffer -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE1D)( AGSContext*, const D3D11_TEXTURE1D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture1D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture1D -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE2D)( AGSContext*, const D3D11_TEXTURE2D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture2D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture2D -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_CREATETEXTURE3D)( AGSContext*, const D3D11_TEXTURE3D_DESC*, const D3D11_SUBRESOURCE_DATA*, ID3D11Texture3D**, AGSAfrTransferType, AGSAfrTransferEngine ); ///< \ref agsDriverExtensionsDX11_CreateTexture3D -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEENDWRITES)( AGSContext*, ID3D11Resource*, const D3D11_RECT*, const unsigned int*, unsigned int ); ///< \ref agsDriverExtensionsDX11_NotifyResourceEndWrites -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEBEGINALLACCESS)( AGSContext*, ID3D11Resource* ); ///< \ref agsDriverExtensionsDX11_NotifyResourceBeginAllAccess -typedef AMD_AGS_API AGSReturnCode (*AGS_DRIVEREXTENSIONSDX11_NOTIFYRESOURCEENDALLACCESS)( AGSContext*, ID3D11Resource* ); ///< \ref agsDriverExtensionsDX11_NotifyResourceEndAllAccess -/// @} - #ifdef __cplusplus } // extern "C" #endif diff --git a/src/3rdparty/ags/repo.json b/src/3rdparty/ags/repo.json index b00f125cdd..5acc6559d7 100644 --- a/src/3rdparty/ags/repo.json +++ b/src/3rdparty/ags/repo.json @@ -2,5 +2,6 @@ "home": "https://github.com/GPUOpen-LibrariesAndSDKs/AGS_SDK", "license": "MIT (embeded in source)", "version": "AGS v6.2.0", - "author": "Advanced Micro Devices, Inc" + "author": "Advanced Micro Devices, Inc", + "modified": "CarterLi" } From b7935aa238f5df26e2e374a31ab5c63f9937c594 Mon Sep 17 00:00:00 2001 From: FilippoULIVO <60037944+FilippoULIVO@users.noreply.github.com> Date: Fri, 22 Dec 2023 12:00:46 +0100 Subject: [PATCH 19/81] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 254b4cff98..168c17bf62 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ ### Linux -* Debian / Ubuntu: Download `fastfetch--Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `sudo apt install fastfetch--Linux.deb` +* Debian / Ubuntu: Download `fastfetch--Linux.deb` from [Github release page](https://github.com/fastfetch-cli/fastfetch/releases/latest) and `dpkg -i fastfetch--Linux.deb` * Arch Linux: `sudo pacman -S fastfetch` * Fedora: `sudo dnf install fastfetch` * Gentoo: `sudo emerge --ask app-misc/fastfetch` From e85a4b9ff52a72cdb4e1252120e16161376242b2 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Fri, 22 Dec 2023 16:04:56 +0900 Subject: [PATCH 20/81] refactor(IO): clean up ffAppendFDBuffer for 2 reasons: - Simplify the Code. - ffAppendFDBuffer can't make assumptions about how the read data will be processed, so the trim calls are inappropriate. --- src/common/io/io_unix.c | 56 +++++++++++++++++++------------------- src/common/io/io_windows.c | 55 +++++++++++++++++++++---------------- src/util/FFstrbuf.c | 3 +- 3 files changed, 61 insertions(+), 53 deletions(-) diff --git a/src/common/io/io_unix.c b/src/common/io/io_unix.c index 546231198e..029aaab625 100644 --- a/src/common/io/io_unix.c +++ b/src/common/io/io_unix.c @@ -47,45 +47,45 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) return write(fd, data, dataSize) > 0; } -bool ffAppendFDBuffer(int fd, FFstrbuf* buffer) +static inline void readWithLength(int fd, FFstrbuf* buffer, uint32_t length) { + ffStrbufEnsureFixedLengthFree(buffer, length); ssize_t bytesRead = 0; - - struct stat fileInfo; - if(fstat(fd, &fileInfo) != 0) - return false; - - if (fileInfo.st_size > 0) - { - // optimize for files has a fixed length, - // file can be very large, only keep necessary memory to save time and resources. - ffStrbufEnsureFixedLengthFree(buffer, (uint32_t)fileInfo.st_size); + while( + length > 0 && (bytesRead = read(fd, buffer->chars + buffer->length, length)) > 0 + ) { + buffer->length += (uint32_t) bytesRead; + length -= (uint32_t) bytesRead; } - else - ffStrbufEnsureFree(buffer, 31); - uint32_t free = ffStrbufGetFree(buffer); - // procfs file's st_size is always zero - // choose a signed int type so that can store a native number - ssize_t remain = fileInfo.st_size; +} +static inline void readUntilEOF(int fd, FFstrbuf* buffer) +{ + ffStrbufEnsureFree(buffer, 31); + uint32_t available = ffStrbufGetFree(buffer); + ssize_t bytesRead = 0; while( - (bytesRead = read(fd, buffer->chars + buffer->length, free)) > 0 + (bytesRead = read(fd, buffer->chars + buffer->length, available)) > 0 ) { buffer->length += (uint32_t) bytesRead; - // if remain > 0, it means there is some data left in the file. - // if remain == 0, it means reading has completed, no need to grow up the buffer. - // if remain < 0, we are reading a file from procfs/sysfs and its st_size is zero, - // we cannot detect how many data remains in the file, we only can call ffStrbufEnsureFree and read again. - remain -= bytesRead; - if((uint32_t) bytesRead == free && remain != 0) + if((uint32_t) bytesRead == available) ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. - free = ffStrbufGetFree(buffer); + available = ffStrbufGetFree(buffer); } +} - buffer->chars[buffer->length] = '\0'; +bool ffAppendFDBuffer(int fd, FFstrbuf* buffer) +{ + struct stat fileInfo; + if(fstat(fd, &fileInfo) != 0) + return false; + + if (fileInfo.st_size > 0) + readWithLength(fd, buffer, (uint32_t)fileInfo.st_size); + else + readUntilEOF(fd, buffer); - ffStrbufTrimRight(buffer, '\n'); - ffStrbufTrimRight(buffer, ' '); + buffer->chars[buffer->length] = '\0'; return buffer->length > 0; } diff --git a/src/common/io/io_windows.c b/src/common/io/io_windows.c index e53a1cee6d..1e0a889f52 100644 --- a/src/common/io/io_windows.c +++ b/src/common/io/io_windows.c @@ -35,43 +35,50 @@ bool ffWriteFileData(const char* fileName, size_t dataSize, const void* data) return !!WriteFile(handle, data, (DWORD)dataSize, &written, NULL); } -bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer) +static inline void readWithLength(HANDLE handle, FFstrbuf* buffer, uint32_t length) { + ffStrbufEnsureFixedLengthFree(buffer, length); DWORD bytesRead = 0; - - LARGE_INTEGER fileSize; - if(!GetFileSizeEx(handle, &fileSize)) - fileSize.QuadPart = 0; - - if (fileSize.QuadPart > 0) - { - // optimize for files has a fixed length, - // file can be very large, only keep necessary memory to save time and resources. - ffStrbufEnsureFixedLengthFree(buffer, (uint32_t)fileSize.QuadPart); + while( + length > 0 && + ReadFile(handle, buffer->chars + buffer->length, length, &bytesRead, NULL) != FALSE && + bytesRead > 0 + ) { + buffer->length += (uint32_t) bytesRead; + length -= (uint32_t) bytesRead; } - else - ffStrbufEnsureFree(buffer, 31); - uint32_t free = ffStrbufGetFree(buffer); - ssize_t remain = fileSize.QuadPart; +} - bool success; +static inline void readUntilEOF(HANDLE handle, FFstrbuf* buffer) +{ + ffStrbufEnsureFree(buffer, 31); + uint32_t available = ffStrbufGetFree(buffer); + DWORD bytesRead = 0; while( - (success = !!ReadFile(handle, buffer->chars + buffer->length, free, &bytesRead, NULL)) && + ReadFile(handle, buffer->chars + buffer->length, available, &bytesRead, NULL) != FALSE && bytesRead > 0 ) { buffer->length += (uint32_t) bytesRead; - remain -= (ssize_t)bytesRead; - if((uint32_t) bytesRead == free && remain != 0) + if((uint32_t) bytesRead == available) ffStrbufEnsureFree(buffer, buffer->allocated - 1); // Doubles capacity every round. -1 for the null byte. - free = ffStrbufGetFree(buffer); + available = ffStrbufGetFree(buffer); } +} - buffer->chars[buffer->length] = '\0'; +bool ffAppendFDBuffer(HANDLE handle, FFstrbuf* buffer) +{ + LARGE_INTEGER fileSize; + if(!GetFileSizeEx(handle, &fileSize)) + fileSize.QuadPart = 0; + + if (fileSize.QuadPart > 0) + readWithLength(handle, buffer, (uint32_t)fileSize.QuadPart); + else + readUntilEOF(handle, buffer); - ffStrbufTrimRight(buffer, '\n'); - ffStrbufTrimRight(buffer, ' '); + buffer->chars[buffer->length] = '\0'; - return success; + return buffer->length > 0; } ssize_t ffReadFileData(const char* fileName, size_t dataSize, void* data) diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 6dfe595897..ce4a5c8e55 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -54,6 +54,7 @@ void ffStrbufEnsureFree(FFstrbuf* strbuf, uint32_t free) strbuf->allocated = allocate; } +// for an empty buffer, free + 1 length memory will be allocated(+1 for the NUL) void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) { uint32_t oldFree = ffStrbufGetFree(strbuf); @@ -64,7 +65,7 @@ void ffStrbufEnsureFixedLengthFree(FFstrbuf* strbuf, uint32_t free) if(strbuf->allocated == 0) { - newCap += strbuf->length + 1; // +1 for the NUL + newCap += strbuf->length + 1; char* newbuf = malloc(sizeof(*strbuf->chars) * newCap); if(strbuf->length == 0) *newbuf = '\0'; From cf98e6f5a196dc8c2f2b87296810069bd8ea2a96 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 23 Dec 2023 00:06:37 +0800 Subject: [PATCH 21/81] Global: remove unexpected trailing line endings Ref: https://github.com/fastfetch-cli/fastfetch/pull/671#issuecomment-1867777472 --- src/detection/bios/bios_linux.c | 23 ++++--------------- src/detection/board/board_linux.c | 19 +++------------ src/detection/chassis/chassis_linux.c | 19 +++------------ src/detection/diskio/diskio_linux.c | 11 +++++---- src/detection/gamepad/gamepad_linux.c | 3 ++- src/detection/gpu/gpu_linux.c | 2 +- src/detection/host/host_linux.c | 23 ++++--------------- .../physicaldisk/physicaldisk_linux.c | 11 +++++---- src/util/FFstrbuf.c | 18 +++++++++++++++ src/util/FFstrbuf.h | 7 ++++++ src/util/smbiosHelper.c | 22 ++++++++++++++++++ src/util/smbiosHelper.h | 6 ++++- 12 files changed, 85 insertions(+), 79 deletions(-) diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index 2c7402c908..fa794d1c22 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -4,25 +4,12 @@ #include -static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) +const char* ffDetectBios(FFBiosResult* bios) { - ffReadFileBuffer(devicesPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffReadFileBuffer(classPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffStrbufClear(buffer); -} - -const char* ffDetectBios(FFBiosResult* bios) -{ - getSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date); - getSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release); - getSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); - getSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version); if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE)) ffStrbufSetStatic(&bios->type, "UEFI"); else diff --git a/src/detection/board/board_linux.c b/src/detection/board/board_linux.c index a4d1225b7c..1092b54ee3 100644 --- a/src/detection/board/board_linux.c +++ b/src/detection/board/board_linux.c @@ -4,23 +4,10 @@ #include -static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) -{ - ffReadFileBuffer(devicesPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffReadFileBuffer(classPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffStrbufClear(buffer); -} - const char* ffDetectBoard(FFBoardResult* board) { - getSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name); - getSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor); - getSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_name", "/sys/class/dmi/id/board_name", &board->name); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_vendor", "/sys/class/dmi/id/board_vendor", &board->vendor); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/board_version", "/sys/class/dmi/id/board_version", &board->version); return NULL; } diff --git a/src/detection/chassis/chassis_linux.c b/src/detection/chassis/chassis_linux.c index e8ce65c822..8c050b8590 100644 --- a/src/detection/chassis/chassis_linux.c +++ b/src/detection/chassis/chassis_linux.c @@ -4,24 +4,11 @@ #include -static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) -{ - ffReadFileBuffer(devicesPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffReadFileBuffer(classPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffStrbufClear(buffer); -} - const char* ffDetectChassis(FFChassisResult* result, FF_MAYBE_UNUSED FFChassisOptions* options) { - getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type); - getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor); - getSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_type", "/sys/class/dmi/id/chassis_type", &result->type); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_vendor", "/sys/class/dmi/id/chassis_vendor", &result->vendor); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/chassis_version", "/sys/class/dmi/id/chassis_version", &result->version); if(result->type.length) { diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index e865581c2a..4a84f25a55 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -41,13 +41,16 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); - ffAppendFileBuffer(pathSysBlock, &device->name); - if (device->name.length > 0) - ffStrbufAppendC(&device->name, ' '); + if (ffAppendFileBuffer(pathSysBlock, &device->name)) + { + ffStrbufTrimRightSpace(&device->name); + if (device->name.length > 0) + ffStrbufAppendC(&device->name, ' '); + } snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); ffAppendFileBuffer(pathSysBlock, &device->name); - ffStrbufTrim(&device->name, ' '); + ffStrbufTrimRightSpace(&device->name); if (device->name.length == 0) ffStrbufSetS(&device->name, devName); diff --git a/src/detection/gamepad/gamepad_linux.c b/src/detection/gamepad/gamepad_linux.c index c68a31d74c..a5273a0fa7 100644 --- a/src/detection/gamepad/gamepad_linux.c +++ b/src/detection/gamepad/gamepad_linux.c @@ -30,7 +30,8 @@ const char* ffDetectGamepad(FFlist* devices /* List of FFGamepadDevice */) FFGamepadDevice* device = (FFGamepadDevice*) ffListAdd(devices); ffStrbufInitS(&device->identifier, entry->d_name); ffStrbufInit(&device->name); - ffAppendFileBuffer(path.chars, &device->name); + if (ffAppendFileBuffer(path.chars, &device->name)) + ffStrbufTrimRightSpace(&device->name); } ffStrbufSubstrBefore(&path, baseLen); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index c21465f0e0..4a170ead4c 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -133,7 +133,7 @@ static void pciDetectDriverName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* ffStrbufAppendC(&gpu->driver, ' '); ffStrbufAppendS(&path, "/module/version"); ffAppendFileBuffer(path.chars, &gpu->driver); - ffStrbufTrimRight(&gpu->driver, ' '); + ffStrbufTrimRightSpace(&gpu->driver); } FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, struct pci_dev* device) diff --git a/src/detection/host/host_linux.c b/src/detection/host/host_linux.c index 269904eaf1..8b11628d68 100644 --- a/src/detection/host/host_linux.c +++ b/src/detection/host/host_linux.c @@ -5,22 +5,9 @@ #include -static void getSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) -{ - ffReadFileBuffer(devicesPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffReadFileBuffer(classPath, buffer); - if(ffIsSmbiosValueSet(buffer)) - return; - - ffStrbufClear(buffer); -} - static void getHostProductName(FFstrbuf* name) { - getSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_name", "/sys/class/dmi/id/product_name", name); if(name->length > 0) return; @@ -42,11 +29,11 @@ static void getHostProductName(FFstrbuf* name) const char* ffDetectHost(FFHostResult* host) { - getSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_family", "/sys/class/dmi/id/product_family", &host->productFamily); getHostProductName(&host->productName); - getSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion); - getSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku); - getSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_version", "/sys/class/dmi/id/product_version", &host->productVersion); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/product_sku", "/sys/class/dmi/id/product_sku", &host->productSku); + ffGetSmbiosValue("/sys/devices/virtual/dmi/id/sys_vendor", "/sys/class/dmi/id/sys_vendor", &host->sysVendor); //KVM/Qemu virtual machine if(ffStrbufStartsWithS(&host->productName, "Standard PC")) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index b946677313..89105dbec2 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -42,13 +42,16 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/vendor", devName); - ffAppendFileBuffer(pathSysBlock, &device->name); - if (device->name.length > 0) - ffStrbufAppendC(&device->name, ' '); + if (ffAppendFileBuffer(pathSysBlock, &device->name)) + { + ffStrbufTrimRightSpace(&device->name); + if (device->name.length > 0) + ffStrbufAppendC(&device->name, ' '); + } snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/model", devName); ffAppendFileBuffer(pathSysBlock, &device->name); - ffStrbufTrim(&device->name, ' '); + ffStrbufTrimRightSpace(&device->name); if (device->name.length == 0) ffStrbufSetS(&device->name, devName); diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index ce4a5c8e55..71e0b4d50d 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -281,6 +281,24 @@ void ffStrbufTrimRight(FFstrbuf* strbuf, char c) strbuf->chars[strbuf->length] = '\0'; } +void ffStrbufTrimRightSpace(FFstrbuf* strbuf) +{ + if(strbuf->length == 0) + return; + + while(ffStrbufEndsWithFn(strbuf, isspace)) + --strbuf->length; + + if(strbuf->allocated == 0) + { + //static string + ffStrbufInitNS(strbuf, strbuf->length, strbuf->chars); + return; + } + + strbuf->chars[strbuf->length] = '\0'; +} + void ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex) { if(startIndex > strbuf->length || startIndex >= endIndex) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index 23859d5f8f..afdf74520d 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -55,6 +55,7 @@ FF_C_PRINTF(2, 3) void ffStrbufSetF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufTrimLeft(FFstrbuf* strbuf, char c); void ffStrbufTrimRight(FFstrbuf* strbuf, char c); +void ffStrbufTrimRightSpace(FFstrbuf* strbuf); void ffStrbufRemoveSubstr(FFstrbuf* strbuf, uint32_t startIndex, uint32_t endIndex); void ffStrbufRemoveS(FFstrbuf* strbuf, const char* str); @@ -454,6 +455,12 @@ static inline FF_C_NODISCARD bool ffStrbufEndsWithS(const FFstrbuf* strbuf, cons return ffStrbufEndsWithNS(strbuf, (uint32_t) strlen(end), end); } +static inline FF_C_NODISCARD bool ffStrbufEndsWithFn(const FFstrbuf* strbuf, int (*fn)(int)) +{ + return strbuf->length == 0 ? false : + fn(strbuf->chars[strbuf->length - 1]); +} + static inline FF_C_NODISCARD bool ffStrbufEndsWith(const FFstrbuf* strbuf, const FFstrbuf* end) { return ffStrbufEndsWithNS(strbuf, end->length, end->chars); diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 88249f6d8a..5f958fc270 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -1,4 +1,5 @@ #include "smbiosHelper.h" +#include "common/io/io.h" bool ffIsSmbiosValueSet(FFstrbuf* value) { @@ -26,3 +27,24 @@ bool ffIsSmbiosValueSet(FFstrbuf* value) !ffStrbufIgnCaseEqualS(value, "N/A") ; } + +#ifdef __linux__ +void ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer) +{ + if (ffReadFileBuffer(devicesPath, buffer)) + { + ffStrbufTrimRightSpace(buffer); + if(ffIsSmbiosValueSet(buffer)) + return; + } + + if (ffReadFileBuffer(classPath, buffer)) + { + ffStrbufTrimRightSpace(buffer); + if(ffIsSmbiosValueSet(buffer)) + return; + } + + ffStrbufClear(buffer); +} +#endif diff --git a/src/util/smbiosHelper.h b/src/util/smbiosHelper.h index 9be3e3120b..f129af5acf 100644 --- a/src/util/smbiosHelper.h +++ b/src/util/smbiosHelper.h @@ -12,4 +12,8 @@ static inline void ffCleanUpSmbiosValue(FFstrbuf* value) ffStrbufClear(value); } -#endif \ No newline at end of file +#ifdef __linux__ +void ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf* buffer); +#endif + +#endif From 113b1b8fc2d74a751a128d62a1d193eb348c428c Mon Sep 17 00:00:00 2001 From: apocelipes Date: Sat, 23 Dec 2023 04:55:14 +0900 Subject: [PATCH 22/81] fix: fix trailing space --- src/detection/battery/battery_linux.c | 7 +++++++ src/detection/displayserver/linux/wayland.c | 1 + src/detection/displayserver/linux/wmde.c | 1 + src/detection/netio/netio_linux.c | 2 +- src/detection/os/os_linux.c | 1 + src/detection/temps/temps_linux.c | 2 ++ src/detection/terminalshell/terminalshell_linux.c | 1 + src/detection/wifi/wifi_linux.c | 2 +- 8 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index c655f34b4e..426d2731f1 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -14,6 +14,7 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option //type must exist and be "Battery" ffStrbufAppendS(dir, "/type"); ffReadFileBuffer(dir->chars, &testBatteryBuffer); + ffStrbufTrimRightSpace(&testBatteryBuffer); ffStrbufSubstrBefore(dir, dirLength); if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Battery") != 0) @@ -22,6 +23,7 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option //scope may not exist or must not be "Device" ffStrbufAppendS(dir, "/scope"); ffReadFileBuffer(dir->chars, &testBatteryBuffer); + ffStrbufTrimRightSpace(&testBatteryBuffer); ffStrbufSubstrBefore(dir, dirLength); if(ffStrbufIgnCaseCompS(&testBatteryBuffer, "Device") == 0) @@ -48,25 +50,30 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option ffStrbufInit(&result->manufacturer); ffStrbufAppendS(dir, "/manufacturer"); ffReadFileBuffer(dir->chars, &result->manufacturer); + ffStrbufTrimRightSpace(&result->manufacturer); ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->modelName); ffStrbufAppendS(dir, "/model_name"); ffReadFileBuffer(dir->chars, &result->modelName); + ffStrbufTrimRightSpace(&result->modelName); ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->technology); ffStrbufAppendS(dir, "/technology"); ffReadFileBuffer(dir->chars, &result->technology); + ffStrbufTrimRightSpace(&result->technology); ffStrbufSubstrBefore(dir, dirLength); ffStrbufInit(&result->status); ffStrbufAppendS(dir, "/status"); ffReadFileBuffer(dir->chars, &result->status); + ffStrbufTrimRightSpace(&result->status); ffStrbufSubstrBefore(dir, dirLength); ffStrbufAppendS(dir, "/cycle_count"); ffReadFileBuffer(dir->chars, &testBatteryBuffer); + ffStrbufTrimRightSpace(&testBatteryBuffer); ffStrbufSubstrBefore(dir, dirLength); if(dir->length) result->cycleCount = (uint32_t) ffStrbufToUInt(&testBatteryBuffer, 0); diff --git a/src/detection/displayserver/linux/wayland.c b/src/detection/displayserver/linux/wayland.c index 559587fa58..3678e118cc 100644 --- a/src/detection/displayserver/linux/wayland.c +++ b/src/detection/displayserver/linux/wayland.c @@ -50,6 +50,7 @@ static void waylandDetectWM(int fd, FFDisplayServerResult* result) FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate(); ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed. ffReadFileBuffer(procPath.chars, &result->wmProcessName); + ffStrbufTrimRightSpace(&result->wmProcessName); ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path } diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 971b14d292..625f04e47a 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -326,6 +326,7 @@ static const char* getFromProcesses(FFDisplayServerResult* result) //We check the cmdline for the process name, because it is not trimmed. ffStrbufAppendS(&procPath, "/cmdline"); ffReadFileBuffer(procPath.chars, &processName); + ffStrbufTrimRightSpace(&processName); ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments ffStrbufSubstrAfterLastC(&processName, '/'); diff --git a/src/detection/netio/netio_linux.c b/src/detection/netio/netio_linux.c index 2b1f244789..2f0ee9dcfc 100644 --- a/src/detection/netio/netio_linux.c +++ b/src/detection/netio/netio_linux.c @@ -9,7 +9,7 @@ static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, FFstrbuf* path, FFlist* result) { ffStrbufSetF(path, "/sys/class/net/%s/operstate", ifName); - if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up")) + if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up\n")) return; FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result); diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 346b2937ac..84a213edc3 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -126,6 +126,7 @@ static void getDebianVersion(FFOSResult* result) { FF_STRBUF_AUTO_DESTROY debianVersion = ffStrbufCreate(); ffAppendFileBuffer("/etc/debian_version", &debianVersion); + ffStrbufTrimRightSpace(&debianVersion); if (!debianVersion.length) return; ffStrbufSet(&result->version, &debianVersion); ffStrbufSet(&result->versionID, &debianVersion); diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index e9b51215a8..5c8b390787 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -26,6 +26,7 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffStrbufAppendS(dir, "name"); ffReadFileBuffer(dir->chars, &value->name); + ffStrbufTrimRightSpace(&value->name); ffStrbufSubstrBefore(dir, dirLength); ffStrbufAppendS(dir, "device/class"); @@ -35,6 +36,7 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffStrbufAppendS(dir, "device/device/class"); ffReadFileBuffer(dir->chars, &valueBuffer); } + ffStrbufTrimRightSpace(&valueBuffer); if(valueBuffer.length) value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 3fde133c4d..bc7f4027f8 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -37,6 +37,7 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex if(ffAppendFileBuffer(cmdlineFilePath, exe)) { + ffStrbufTrimRightSpace(exe); ffStrbufSubstrBeforeFirstC(exe, '\0'); //Trim the arguments ffStrbufTrimLeft(exe, '-'); //Happens in TTY } diff --git a/src/detection/wifi/wifi_linux.c b/src/detection/wifi/wifi_linux.c index 24eda8da3f..5c500f50d5 100644 --- a/src/detection/wifi/wifi_linux.c +++ b/src/detection/wifi/wifi_linux.c @@ -248,7 +248,7 @@ static const char* detectWifiWithIoctls(FFlist* result) item->conn.txRate = 0.0/0.0; ffStrbufSetF(&path, "/sys/class/net/%s/operstate", i->if_name); - if(!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up")) + if (!ffAppendFileBuffer(path.chars, &item->inf.status) || !ffStrbufEqualS(&item->inf.status, "up\n")) continue; FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); From d2d4ee89d86851323b44fc9646a772324942ca18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 19:41:20 +0800 Subject: [PATCH 23/81] GPU (WSL): fix gpu temp detection for nvidia cards --- src/detection/gpu/gpu_wsl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index 1fe09fb1a2..a847a53ecb 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -98,7 +98,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF const char* vendorStr = ffGetGPUVendorString((unsigned) hardwareId.vendorID); ffStrbufSetStatic(&gpu->vendor, vendorStr); - if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && options->driverSpecific) + if (vendorStr == FF_GPU_VENDOR_NAME_NVIDIA && (options->driverSpecific || options->temp)) { FFGpuDriverCondition cond = { .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID, From be38182ab21a22df579f4274f88aa791557a8bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 19:42:10 +0800 Subject: [PATCH 24/81] Disk (WSL): fix Windows volume detection --- src/detection/disk/disk_linux.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index ae94117c24..c4c1136a1a 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -26,8 +26,11 @@ static bool isPhysicalDevice(const struct mntent* device) if(ffStrEquals(device->mnt_dir, "/")) return true; + if(ffStrEquals(device->mnt_fsname, "none")) + return false; + //DrvFs is a filesystem plugin to WSL that was designed to support interop between WSL and the Windows filesystem. - if(ffStrEquals(device->mnt_fsname, "drvfs")) + if(ffStrEquals(device->mnt_type, "9p")) return true; //ZFS pool From 97c69669393b553e0c3ee55feef11f4e614e9eec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 20:32:43 +0800 Subject: [PATCH 25/81] Disk (Linux): detect subvolume first Fix #674 --- src/detection/disk/disk_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index c4c1136a1a..8b3620af09 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -223,10 +223,10 @@ static void detectType(const FFlist* disks, FFDisk* currentDisk) { if(ffStrbufStartsWithS(¤tDisk->mountpoint, "/boot") || ffStrbufStartsWithS(¤tDisk->mountpoint, "/efi")) currentDisk->type = FF_DISK_VOLUME_TYPE_HIDDEN_BIT; - else if(isRemovable(currentDisk)) - currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else if(isSubvolume(disks, currentDisk)) currentDisk->type = FF_DISK_VOLUME_TYPE_SUBVOLUME_BIT; + else if(isRemovable(currentDisk)) + currentDisk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else currentDisk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; } From 34b0bbac263ab2ba953a58d064d146fc0bc33fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 20:52:05 +0800 Subject: [PATCH 26/81] PhysicalDisk (Linux): be more careful to detect connection type --- src/detection/physicaldisk/physicaldisk_linux.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 89105dbec2..52f79ff206 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -70,15 +70,12 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) ffStrbufInit(&device->interconnect); if (strstr(pathSysDeviceReal, "/usb") != NULL) ffStrbufSetS(&device->interconnect, "usb"); + if (strstr(pathSysDeviceReal, "/ata") != NULL) + ffStrbufSetS(&device->interconnect, "ata"); else { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); - if (!ffAppendFileBuffer(pathSysBlock, &device->interconnect)) - { - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/uevent", devName); - if (ffParsePropFile(pathSysBlock, "DEVTYPE=", &device->interconnect)) - ffStrbufSubstrBeforeLastC(&device->interconnect, '_'); - } + ffAppendFileBuffer(pathSysBlock, &device->interconnect); } } From 58e8403e1629eea03b830353f33c2686cda4ac89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 20:53:11 +0800 Subject: [PATCH 27/81] Disk (Linux): be more careful to detect external type --- src/detection/disk/disk_linux.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 8b3620af09..69adbcea02 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -210,10 +210,11 @@ static bool isRemovable(FFDisk* currentDisk) if (!ffStrStartsWith(partitionName, entry->d_name)) continue; - // /sys/block/sdx/device/delete + // /sys/block/sdx/removable ffStrbufAppendS(&basePath, entry->d_name); - ffStrbufAppendS(&basePath, "/device/delete"); - return ffPathExists(basePath.chars, FF_PATHTYPE_FILE); + ffStrbufAppendS(&basePath, "/removable"); + char removableChar = '0'; + return ffReadFileData(basePath.chars, 1, &removableChar) > 0 && removableChar == '1'; } return false; From ef8bd63075f32b7dcd605a3ed726cefb88125583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 21:33:57 +0800 Subject: [PATCH 28/81] PhysicalDisk (Linux): remove trailing spaces --- src/detection/physicaldisk/physicaldisk_linux.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 52f79ff206..6e6d2c8540 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -75,7 +75,8 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) else { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); - ffAppendFileBuffer(pathSysBlock, &device->interconnect); + if (ffAppendFileBuffer(pathSysBlock, &device->interconnect)) + ffStrbufTrimRightSpace(&device->interconnect); } } @@ -109,7 +110,8 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { ffStrbufInit(&device->serial); snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/serial", devName); - ffReadFileBuffer(pathSysBlock, &device->serial); + if (ffReadFileBuffer(pathSysBlock, &device->serial)) + ffStrbufTrimRightSpace(&device->serial); } } From b5a01400e9577357ae758c92d4d290e6cd2e9121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 22:31:36 +0800 Subject: [PATCH 29/81] PhysicalDisk (Linux): detect more interconnect type --- src/detection/physicaldisk/physicaldisk_linux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 6e6d2c8540..1081e24b76 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -70,8 +70,10 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) ffStrbufInit(&device->interconnect); if (strstr(pathSysDeviceReal, "/usb") != NULL) ffStrbufSetS(&device->interconnect, "usb"); - if (strstr(pathSysDeviceReal, "/ata") != NULL) + else if (strstr(pathSysDeviceReal, "/ata") != NULL) ffStrbufSetS(&device->interconnect, "ata"); + else if (strstr(pathSysDeviceReal, "/nvme") != NULL) + ffStrbufSetS(&device->interconnect, "nvme"); else { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); From 02999ae4bfdba7cc071208680bdaefc3aada649c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 22:34:45 +0800 Subject: [PATCH 30/81] PhysicalDisk (Linux): detect readonly --- src/detection/physicaldisk/physicaldisk.h | 2 ++ src/detection/physicaldisk/physicaldisk_linux.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index eea569d2a2..e3889ea6a1 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -10,6 +10,8 @@ typedef enum FFPhysicalDiskType FF_PHYSICALDISK_TYPE_FIXED = 1 << 2, FF_PHYSICALDISK_TYPE_REMOVABLE = 1 << 3, + + FF_PHYSICALDISK_TYPE_READONLY = 1 << 2, } FFPhysicalDiskType; typedef struct FFPhysicalDiskResult diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 1081e24b76..3eaa74ce9f 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -109,6 +109,13 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) device->type |= removableChar == '1' ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; } + { + char roChar = '0'; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/ro", devName); + if (ffReadFileData(pathSysBlock, 1, &roChar) > 0) + device->type |= roChar == '1' ? FF_PHYSICALDISK_TYPE_READONLY : 0; + } + { ffStrbufInit(&device->serial); snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/serial", devName); From c100e0dff78718b738602361266a91234050d88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 24 Dec 2023 23:26:33 +0800 Subject: [PATCH 31/81] PhysicalDisk (Windows): detect CDROMs; detect read-only --- src/detection/diskio/diskio_windows.c | 145 ++++++---- .../physicaldisk/physicaldisk_windows.c | 264 ++++++++++-------- 2 files changed, 237 insertions(+), 172 deletions(-) diff --git a/src/detection/diskio/diskio_windows.c b/src/detection/diskio/diskio_windows.c index de7ef5c1c2..1317057d26 100644 --- a/src/detection/diskio/diskio_windows.c +++ b/src/detection/diskio/diskio_windows.c @@ -5,78 +5,99 @@ #include #include -const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFDiskIOOptions* options) { - wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive"; - wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive"); - for (uint32_t idev = 0; ; ++idev) + FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + return false; + + DWORD retSize; + char sddBuffer[4096]; + if(!DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &sddBuffer, + sizeof(sddBuffer), + &retSize, + NULL + ) || retSize == 0) + return true; + + FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); + STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; + + ffStrbufInit(&device->name); + if (sdd->VendorIdOffset != 0) { - _ultow(idev, pNum, 10); - - FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - break; - - DWORD retSize; - char sddBuffer[4096]; - if(!DeviceIoControl( - hDevice, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &sddBuffer, - sizeof(sddBuffer), - &retSize, - NULL - ) || retSize == 0) - continue; - - FFDiskIOResult* device = (FFDiskIOResult*) ffListAdd(result); - STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; - - ffStrbufInit(&device->name); - if (sdd->VendorIdOffset != 0) - { - ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); - ffStrbufTrim(&device->name, ' '); - } - if (sdd->ProductIdOffset != 0) - { - if (device->name.length) - ffStrbufAppendC(&device->name, ' '); + ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); + ffStrbufTrim(&device->name, ' '); + } + if (sdd->ProductIdOffset != 0) + { + if (device->name.length) + ffStrbufAppendC(&device->name, ' '); - ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); - ffStrbufTrimRight(&device->name, ' '); - } + ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); + ffStrbufTrimRight(&device->name, ' '); + } - if (!device->name.length) - ffStrbufAppendF(&device->name, "PhysicalDrive%u", (unsigned) idev); + if (!device->name.length) + ffStrbufSetWS(&device->name, szDevice); - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) - { - ffStrbufDestroy(&device->name); - result->length--; - continue; - } + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + return true; + } - ffStrbufInitWS(&device->devPath, szDevice); + ffStrbufInitWS(&device->devPath, szDevice); - DISK_PERFORMANCE dp = {}; - if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &dp, sizeof(dp), &retSize, NULL)) + DISK_PERFORMANCE dp = {}; + if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, &dp, sizeof(dp), &retSize, NULL)) + { + device->bytesRead = (uint64_t) dp.BytesRead.QuadPart; + device->readCount = (uint64_t) dp.ReadCount; + device->bytesWritten = (uint64_t) dp.BytesWritten.QuadPart; + device->writeCount = (uint64_t) dp.WriteCount; + } + else + { + ffStrbufDestroy(&device->name); + result->length--; + } + + return true; +} + +const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) +{ + { + wchar_t szPhysicalDrive[32] = L"\\\\.\\PhysicalDrive"; + wchar_t* pNum = szPhysicalDrive + strlen("\\\\.\\PhysicalDrive"); + for (uint32_t idev = 0; ; ++idev) { - device->bytesRead = (uint64_t) dp.BytesRead.QuadPart; - device->readCount = (uint64_t) dp.ReadCount; - device->bytesWritten = (uint64_t) dp.BytesWritten.QuadPart; - device->writeCount = (uint64_t) dp.WriteCount; + _ultow(idev, pNum, 10); + + if (!detectPhysicalDisk(szPhysicalDrive, result, options)) + break; } - else + } + + { + wchar_t szCdrom[32] = L"\\\\.\\CDROM"; + wchar_t* pNum = szCdrom + strlen("\\\\.\\CDROM"); + for (uint32_t idev = 0; ; ++idev) { - ffStrbufDestroy(&device->name); - result->length--; - continue; + _ultow(idev, pNum, 10); + + if (!detectPhysicalDisk(szCdrom, result, options)) + break; } } diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index 1ad1a5779b..d3fc246b9f 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -5,126 +5,170 @@ #include #include -const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysicalDiskOptions* options) { - wchar_t szDevice[32] = L"\\\\.\\PhysicalDrive"; - wchar_t* pNum = szDevice + strlen("\\\\.\\PhysicalDrive"); - for (uint32_t idev = 0; ; ++idev) + FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hDevice == INVALID_HANDLE_VALUE) + return false; + + DWORD retSize; + char sddBuffer[4096]; + if(!DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &sddBuffer, + sizeof(sddBuffer), + &retSize, + NULL + ) || retSize == 0) + return true; + + FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); + device->type = FF_PHYSICALDISK_TYPE_NONE; + STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; + + ffStrbufInit(&device->name); + if (sdd->VendorIdOffset != 0) { - _ultow(idev, pNum, 10); - - FF_AUTO_CLOSE_FD HANDLE hDevice = CreateFileW(szDevice, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hDevice == INVALID_HANDLE_VALUE) - break; - - DWORD retSize; - char sddBuffer[4096]; - if(!DeviceIoControl( - hDevice, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &sddBuffer, - sizeof(sddBuffer), - &retSize, - NULL - ) || retSize == 0) - continue; - - FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); - device->type = FF_PHYSICALDISK_TYPE_NONE; - STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*) sddBuffer; - - ffStrbufInit(&device->name); - if (sdd->VendorIdOffset != 0) - { - ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); - ffStrbufTrim(&device->name, ' '); - } - if (sdd->ProductIdOffset != 0) - { - if (device->name.length) - ffStrbufAppendC(&device->name, ' '); + ffStrbufSetS(&device->name, (const char*) sddBuffer + sdd->VendorIdOffset); + ffStrbufTrim(&device->name, ' '); + } + if (sdd->ProductIdOffset != 0) + { + if (device->name.length) + ffStrbufAppendC(&device->name, ' '); - ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); - ffStrbufTrimRight(&device->name, ' '); - } + ffStrbufAppendS(&device->name, (const char*) sddBuffer + sdd->ProductIdOffset); + ffStrbufTrimRight(&device->name, ' '); + } - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) - { - ffStrbufDestroy(&device->name); - result->length--; - continue; - } + if (!device->name.length) + ffStrbufSetWS(&device->name, szDevice); - ffStrbufInitWS(&device->devPath, szDevice); - ffStrbufInit(&device->serial); - if (sdd->SerialNumberOffset != 0) - { - ffStrbufSetS(&device->serial, (const char*) sddBuffer + sdd->SerialNumberOffset); - ffStrbufTrim(&device->serial, ' '); - } + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) + { + ffStrbufDestroy(&device->name); + result->length--; + return true; + } + + ffStrbufInitWS(&device->devPath, szDevice); + ffStrbufInit(&device->serial); + if (sdd->SerialNumberOffset != 0) + { + ffStrbufSetS(&device->serial, (const char*) sddBuffer + sdd->SerialNumberOffset); + ffStrbufTrim(&device->serial, ' '); + } - device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; - ffStrbufInit(&device->interconnect); - switch (sdd->BusType) + ffStrbufInit(&device->interconnect); + switch (sdd->BusType) + { + case BusTypeUnknown: ffStrbufSetStatic(&device->interconnect, "Unknown"); break; + case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "Scsi"); break; + case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "Atapi"); break; + case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "Ata"); break; + case BusType1394: ffStrbufSetStatic(&device->interconnect, "1394"); break; + case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "Ssa"); break; + case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibra"); break; + case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "Usb"); break; + case BusTypeRAID: ffStrbufSetStatic(&device->interconnect, "RAID"); break; + case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iScsi"); break; + case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "Sas"); break; + case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "Sata"); break; + case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "Sd"); break; + case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "Mmc"); break; + case BusTypeVirtual: ffStrbufSetStatic(&device->interconnect, "Virtual"); break; + case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "FileBackedVirtual"); break; + case BusTypeSpaces: ffStrbufSetStatic(&device->interconnect, "Spaces"); break; + case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "Nvme"); break; + case BusTypeSCM: ffStrbufSetStatic(&device->interconnect, "SCM"); break; + case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "Ufs"); break; + default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break; + } + + DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &dspd, + sizeof(dspd), + &retSize, + NULL + ) && retSize == sizeof(dspd)) + device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + + DISK_GEOMETRY_EX dge = {}; + if(DeviceIoControl( + hDevice, + IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, + 0, + &dge, + sizeof(dge), + &retSize, + NULL)) + device->size = (uint64_t) dge.DiskSize.QuadPart; + else + device->size = 0; + + GET_MEDIA_TYPES gmt = {}; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_GET_MEDIA_TYPES_EX, + NULL, + 0, + &gmt, + sizeof(gmt), + &retSize, + NULL) && gmt.MediaInfoCount > 0 + ) + { + __typeof__(gmt.MediaInfo[0].DeviceSpecific.DiskInfo)* diskInfo = &gmt.MediaInfo[0].DeviceSpecific.DiskInfo; + if (diskInfo->MediaCharacteristics & MEDIA_READ_ONLY) + device->type |= FF_PHYSICALDISK_TYPE_READONLY; + if (device->size == 0) + device->size = (uint64_t) diskInfo->NumberMediaSides * diskInfo->TracksPerCylinder * diskInfo->SectorsPerTrack * diskInfo->BytesPerSector; + } + + return true; +} + +const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) +{ + { + wchar_t szPhysicalDrive[32] = L"\\\\.\\PhysicalDrive"; + wchar_t* pNum = szPhysicalDrive + strlen("\\\\.\\PhysicalDrive"); + for (uint32_t idev = 0; ; ++idev) { - case BusTypeUnknown: ffStrbufSetStatic(&device->interconnect, "Unknown"); break; - case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "Scsi"); break; - case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "Atapi"); break; - case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "Ata"); break; - case BusType1394: ffStrbufSetStatic(&device->interconnect, "1394"); break; - case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "Ssa"); break; - case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibra"); break; - case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "Usb"); break; - case BusTypeRAID: ffStrbufSetStatic(&device->interconnect, "RAID"); break; - case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iScsi"); break; - case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "Sas"); break; - case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "Sata"); break; - case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "Sd"); break; - case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "Mmc"); break; - case BusTypeVirtual: ffStrbufSetStatic(&device->interconnect, "Virtual"); break; - case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "FileBackedVirtual"); break; - case BusTypeSpaces: ffStrbufSetStatic(&device->interconnect, "Spaces"); break; - case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "Nvme"); break; - case BusTypeSCM: ffStrbufSetStatic(&device->interconnect, "SCM"); break; - case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "Ufs"); break; - default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break; + _ultow(idev, pNum, 10); + + if (!detectPhysicalDisk(szPhysicalDrive, result, options)) + break; } + } - DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; - if(DeviceIoControl( - hDevice, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceSeekPenaltyProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &dspd, - sizeof(dspd), - &retSize, - NULL - ) && retSize == sizeof(dspd)) - device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; - - DISK_GEOMETRY_EX dge = {}; - if(DeviceIoControl( - hDevice, - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, - NULL, - 0, - &dge, - sizeof(dge), - &retSize, - NULL)) - device->size = (uint64_t) dge.DiskSize.QuadPart; - else - device->size = 0; + { + wchar_t szCdrom[32] = L"\\\\.\\CDROM"; + wchar_t* pNum = szCdrom + strlen("\\\\.\\CDROM"); + for (uint32_t idev = 0; ; ++idev) + { + _ultow(idev, pNum, 10); + + if (!detectPhysicalDisk(szCdrom, result, options)) + break; + } } return NULL; From e7aa6c37575589a1c50a51fffee16ff59247d5a5 Mon Sep 17 00:00:00 2001 From: apocelipes Date: Mon, 25 Dec 2023 11:52:30 +0900 Subject: [PATCH 32/81] fix(Battery): fix overflow and uninitializations of battery cycle counts --- src/detection/battery/battery_android.c | 1 + src/detection/battery/battery_apple.c | 4 +++- src/detection/battery/battery_linux.c | 8 ++++++-- src/detection/battery/battery_windows.c | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/detection/battery/battery_android.c b/src/detection/battery/battery_android.c index 7b3a2e0843..6ddf3bbfee 100644 --- a/src/detection/battery/battery_android.c +++ b/src/detection/battery/battery_android.c @@ -71,6 +71,7 @@ static const char* parseDumpsys(FFBatteryOptions* options, FFlist* results) FFBatteryResult* battery = ffListAdd(results); battery->temperature = FF_BATTERY_TEMP_UNSET; + battery->cycleCount = 0; ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->modelName); ffStrbufInit(&battery->status); diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 602a61fc71..213cef8532 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -56,7 +56,9 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) ffStrbufAppendS(&battery->modelName, "Built-in"); } - ffCfDictGetInt(properties, CFSTR("CycleCount"), (int32_t*) &battery->cycleCount); + int32_t cycleCount = 0; + ffCfDictGetInt(properties, CFSTR("CycleCount"), &cycleCount); + battery->cycleCount = cycleCount < 0 ? 0 : (uint32_t) cycleCount; if (!ffCfDictGetBool(properties, CFSTR("ExternalConnected"), &boolValue) && boolValue) ffStrbufAppendS(&battery->status, "AC connected, "); diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 426d2731f1..49daded722 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -75,8 +75,12 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option ffReadFileBuffer(dir->chars, &testBatteryBuffer); ffStrbufTrimRightSpace(&testBatteryBuffer); ffStrbufSubstrBefore(dir, dirLength); - if(dir->length) - result->cycleCount = (uint32_t) ffStrbufToUInt(&testBatteryBuffer, 0); + if (dir->length) + { + int64_t cycleCount = 0; + cycleCount = (int64_t) strtoll(testBatteryBuffer.chars, NULL, 10); + result->cycleCount = cycleCount < 0 || cycleCount > UINT32_MAX ? 0 : (uint32_t) cycleCount; + } result->temperature = FF_BATTERY_TEMP_UNSET; if (options->temp) diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 283ccc1356..9deea532cf 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -150,7 +150,7 @@ static const char* detectWithNtApi(FF_MAYBE_UNUSED FFBatteryOptions* options, FF ffStrbufInit(&battery->manufacturer); ffStrbufInit(&battery->technology); ffStrbufInit(&battery->status); - battery->temperature = 0.0/0.0; + battery->temperature = FF_BATTERY_TEMP_UNSET; battery->cycleCount = 0; battery->capacity = info.RemainingCapacity * 100.0 / info.MaxCapacity; From 350388295dedc1dc2c6a77c022da4c23dc629ab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 22 Dec 2023 10:14:51 +0800 Subject: [PATCH 33/81] Doc: fix `--help` messages --- src/data/help.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/help.json b/src/data/help.json index f30c5ed5b7..946af06038 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -82,7 +82,7 @@ } } ], - "pseudo": [ + "General": [ { "long": "thread", "desc": "Use separate threads to send HTTP requests", From 3b6d5468dac18509e7697bb263679991c69d7ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 08:55:17 +0800 Subject: [PATCH 34/81] PhysicalDisk (macOS): detect read-only --- src/detection/physicaldisk/physicaldisk.h | 3 ++- .../physicaldisk/physicaldisk_apple.c | 3 +++ .../physicaldisk/physicaldisk_linux.c | 2 +- .../physicaldisk/physicaldisk_windows.c | 2 ++ src/modules/physicaldisk/physicaldisk.c | 20 +++++++++++++++++-- 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index e3889ea6a1..54fa1bc480 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -11,7 +11,8 @@ typedef enum FFPhysicalDiskType FF_PHYSICALDISK_TYPE_FIXED = 1 << 2, FF_PHYSICALDISK_TYPE_REMOVABLE = 1 << 3, - FF_PHYSICALDISK_TYPE_READONLY = 1 << 2, + FF_PHYSICALDISK_TYPE_READWRITE = 1 << 4, + FF_PHYSICALDISK_TYPE_READONLY = 1 << 5, } FFPhysicalDiskType; typedef struct FFPhysicalDiskResult diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index bd186fab1f..645dad330b 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -52,6 +52,9 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) FF_CFTYPE_AUTO_RELEASE CFBooleanRef removable = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaRemovableKey), kCFAllocatorDefault, kNilOptions); device->type |= CFBooleanGetValue(removable) ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; + FF_CFTYPE_AUTO_RELEASE CFBooleanRef writable = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaWritableKey), kCFAllocatorDefault, kNilOptions); + device->type |= CFBooleanGetValue(writable) ? FF_PHYSICALDISK_TYPE_READWRITE : FF_PHYSICALDISK_TYPE_READONLY; + FF_CFTYPE_AUTO_RELEASE CFStringRef bsdName = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, kNilOptions); if (bsdName) { diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 3eaa74ce9f..7ffb8c02a0 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -113,7 +113,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) char roChar = '0'; snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/ro", devName); if (ffReadFileData(pathSysBlock, 1, &roChar) > 0) - device->type |= roChar == '1' ? FF_PHYSICALDISK_TYPE_READONLY : 0; + device->type |= roChar == '1' ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; } { diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index d3fc246b9f..f39909747d 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -138,6 +138,8 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic __typeof__(gmt.MediaInfo[0].DeviceSpecific.DiskInfo)* diskInfo = &gmt.MediaInfo[0].DeviceSpecific.DiskInfo; if (diskInfo->MediaCharacteristics & MEDIA_READ_ONLY) device->type |= FF_PHYSICALDISK_TYPE_READONLY; + else if (diskInfo->MediaCharacteristics & MEDIA_READ_WRITE) + device->type |= FF_PHYSICALDISK_TYPE_READWRITE; if (device->size == 0) device->size = (uint64_t) diskInfo->NumberMediaSides * diskInfo->TracksPerCylinder * diskInfo->SectorsPerTrack * diskInfo->BytesPerSector; } diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 05911eb64c..d5bacd4c71 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -63,22 +63,31 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) : dev->type & FF_PHYSICALDISK_TYPE_FIXED ? "Fixed" : ""; + const char* readOnlyType = dev->type & FF_PHYSICALDISK_TYPE_READONLY + ? "Read-only" + : ""; if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - if (physicalType[0] || removableType[0]) + if (physicalType[0] || removableType[0] || readOnlyType[0]) { ffStrbufAppendS(&buffer, " ["); if (physicalType[0]) ffStrbufAppendS(&buffer, physicalType); if (removableType[0]) { - if (physicalType[0]) + if (buffer.chars[buffer.length - 1] != '[') ffStrbufAppendS(&buffer, ", "); ffStrbufAppendS(&buffer, removableType); } + if (readOnlyType[0]) + { + if (buffer.chars[buffer.length - 1] != '[') + ffStrbufAppendS(&buffer, ", "); + ffStrbufAppendS(&buffer, readOnlyType); + } ffStrbufAppendC(&buffer, ']'); } ffStrbufPutTo(&buffer, stdout); @@ -193,6 +202,13 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut yyjson_mut_obj_add_bool(doc, obj, "removable", false); else yyjson_mut_obj_add_null(doc, obj, "removable"); + + if (dev->type & FF_PHYSICALDISK_TYPE_READONLY) + yyjson_mut_obj_add_bool(doc, obj, "readOnly", true); + else if (dev->type & FF_PHYSICALDISK_TYPE_READWRITE) + yyjson_mut_obj_add_bool(doc, obj, "readOnly", false); + else + yyjson_mut_obj_add_null(doc, obj, "readOnly"); } FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) From cb68dccd0e416124e65b9c1fcfc86bca923eb869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 09:00:16 +0800 Subject: [PATCH 35/81] GPU (AMD): fix a silly bug --- src/detection/gpu/gpu_amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 272a85db5b..3efd23c402 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -28,7 +28,7 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu ffagsDeInitialize(apiHandle); } - if (!gpuInfo.numDevices == 0) + if (gpuInfo.numDevices == 0) return "loading ags library failed or no AMD gpus found"; AGSDeviceInfo* device = NULL; From 5e85864ab038ecc025bfd606e72b7494fd5fe493 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 25 Dec 2023 09:56:11 +0800 Subject: [PATCH 36/81] PhysicalDisk (FreeBSD): detect read-only --- src/detection/physicaldisk/physicaldisk_bsd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index c23b08aea1..288c0685d3 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -60,6 +60,11 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } device->size = (uint64_t) provider->lg_mediasize; ffStrbufInitMove(&device->name, &name); + + int acr = 1, acw = 1; // TODO: find some documents to verify the usage + if (sscanf(provider->lg_mode, "r%dw%de%*d", &acr, &acw) == 2 && acr) + type |= acw ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; + device->type = type; } From b2cabd2af7924601cba380b3afd6daf0ef49ca0c Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 25 Dec 2023 16:32:34 +0800 Subject: [PATCH 37/81] PhysicalDisk (Linux): detect firmware revision --- src/detection/physicaldisk/physicaldisk.h | 1 + src/detection/physicaldisk/physicaldisk_linux.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index 54fa1bc480..6e9c270032 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -21,6 +21,7 @@ typedef struct FFPhysicalDiskResult FFstrbuf interconnect; FFstrbuf serial; FFstrbuf devPath; + FFstrbuf firmwareRev; FFPhysicalDiskType type; uint64_t size; } FFPhysicalDiskResult; diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 7ffb8c02a0..703d46e5d6 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -56,6 +56,15 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (device->name.length == 0) ffStrbufSetS(&device->name, devName); + char diskseq[8] = ""; + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/diskseq", devName); + ffReadFileData(pathSysBlock, sizeof(diskseq) - 1, diskseq); + char* lineEnding = strchr(diskseq, '\n'); + if (lineEnding) + *lineEnding = '\0'; + if (!ffStrEquals(diskseq, "1")) + ffStrbufAppendF(&device->name, "-%s", diskseq); + if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { ffStrbufDestroy(&device->name); @@ -122,6 +131,13 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (ffReadFileBuffer(pathSysBlock, &device->serial)) ffStrbufTrimRightSpace(&device->serial); } + + { + ffStrbufInit(&device->firmwareRev); + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/firmware_rev", devName); + if (ffReadFileBuffer(pathSysBlock, &device->firmwareRev)) + ffStrbufTrimRightSpace(&device->firmwareRev); + } } return NULL; From d3bcef61da493853a7e6dbc68e1d5f8d40486812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 16:39:58 +0800 Subject: [PATCH 38/81] PhysicalDisk (macOS): detect firmware revision --- src/detection/physicaldisk/physicaldisk_apple.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 645dad330b..1ac7390a22 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -43,6 +43,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); ffStrbufInit(&device->serial); + ffStrbufInit(&device->firmwareRev); ffStrbufInitS(&device->name, deviceName); ffStrbufInit(&device->devPath); ffStrbufInit(&device->interconnect); @@ -79,6 +80,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (deviceCharacteristics) { ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial); + ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductRevisionLevelKey), &device->firmwareRev); CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); if (mediumType) From 3134a04b5c1f3dc1047de5e0940dd76a6f6b8d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 18:12:02 +0800 Subject: [PATCH 39/81] PhysicalDisk (Linux): don't append diskseq --- src/detection/physicaldisk/physicaldisk_linux.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 703d46e5d6..8d8fd8d16d 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -56,15 +56,6 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (device->name.length == 0) ffStrbufSetS(&device->name, devName); - char diskseq[8] = ""; - snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/diskseq", devName); - ffReadFileData(pathSysBlock, sizeof(diskseq) - 1, diskseq); - char* lineEnding = strchr(diskseq, '\n'); - if (lineEnding) - *lineEnding = '\0'; - if (!ffStrEquals(diskseq, "1")) - ffStrbufAppendF(&device->name, "-%s", diskseq); - if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { ffStrbufDestroy(&device->name); From 060082885b10b08d2a56344a57849d5437f80fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 18:21:23 +0800 Subject: [PATCH 40/81] PhysicalDisk: rename firmwareRev to revision --- src/detection/physicaldisk/physicaldisk.h | 2 +- src/detection/physicaldisk/physicaldisk_apple.c | 4 ++-- src/detection/physicaldisk/physicaldisk_linux.c | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index 6e9c270032..15bb7ce511 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -21,7 +21,7 @@ typedef struct FFPhysicalDiskResult FFstrbuf interconnect; FFstrbuf serial; FFstrbuf devPath; - FFstrbuf firmwareRev; + FFstrbuf revision; FFPhysicalDiskType type; uint64_t size; } FFPhysicalDiskResult; diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 1ac7390a22..85ffbbd250 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -43,7 +43,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); ffStrbufInit(&device->serial); - ffStrbufInit(&device->firmwareRev); + ffStrbufInit(&device->revision); ffStrbufInitS(&device->name, deviceName); ffStrbufInit(&device->devPath); ffStrbufInit(&device->interconnect); @@ -80,7 +80,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (deviceCharacteristics) { ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial); - ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductRevisionLevelKey), &device->firmwareRev); + ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductRevisionLevelKey), &device->revision); CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); if (mediumType) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 8d8fd8d16d..4a3a19227e 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -124,10 +124,10 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } { - ffStrbufInit(&device->firmwareRev); + ffStrbufInit(&device->revision); snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/firmware_rev", devName); - if (ffReadFileBuffer(pathSysBlock, &device->firmwareRev)) - ffStrbufTrimRightSpace(&device->firmwareRev); + if (ffReadFileBuffer(pathSysBlock, &device->revision)) + ffStrbufTrimRightSpace(&device->revision); } } From f2da8305c748082bbd505dbd04de43c04ae1bb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 18:22:04 +0800 Subject: [PATCH 41/81] PhysicalDisk (Windows): detect revision --- src/detection/physicaldisk/physicaldisk_windows.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index f39909747d..f1b47b908b 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -65,6 +65,12 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic ffStrbufTrim(&device->serial, ' '); } + if (sdd->ProductRevisionOffset != 0) + { + ffStrbufSetS(&device->revision, (const char*) sddBuffer + sdd->ProductRevisionOffset); + ffStrbufTrim(&device->revision, ' '); + } + device->type |= sdd->RemovableMedia ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; ffStrbufInit(&device->interconnect); From 677f39420bed23d3817c3ad288a862620313c16e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 18:33:39 +0800 Subject: [PATCH 42/81] PhysicalDisk: print product revision --- src/detection/physicaldisk/physicaldisk_bsd.c | 1 + src/modules/physicaldisk/physicaldisk.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index 288c0685d3..513d0f8e1e 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -51,6 +51,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result); ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name); ffStrbufInitMove(&device->serial, &identifier); + ffStrbufInit(&device->revision); ffStrbufInit(&device->interconnect); switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK) { diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index d5bacd4c71..07be887587 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -6,7 +6,7 @@ #include "util/stringUtils.h" #define FF_PHYSICALDISK_DISPLAY_NAME "Physical Disk" -#define FF_PHYSICALDISK_NUM_FORMAT_ARGS 7 +#define FF_PHYSICALDISK_NUM_FORMAT_ARGS 9 static int sortDevices(const FFPhysicalDiskResult* left, const FFPhysicalDiskResult* right) { @@ -94,6 +94,8 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) } else { + if (dev->type & FF_PHYSICALDISK_TYPE_READWRITE) + readOnlyType = "Read-write"; ffParseSize(dev->size, &buffer); ffPrintFormatString(key.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, FF_PHYSICALDISK_NUM_FORMAT_ARGS, (FFformatarg[]){ {FF_FORMAT_ARG_TYPE_STRBUF, &buffer}, @@ -103,6 +105,8 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &dev->devPath}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->serial}, {FF_FORMAT_ARG_TYPE_STRING, removableType}, + {FF_FORMAT_ARG_TYPE_STRING, readOnlyType}, + {FF_FORMAT_ARG_TYPE_STRBUF, &dev->revision}, }); } ++index; @@ -209,6 +213,8 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut yyjson_mut_obj_add_bool(doc, obj, "readOnly", false); else yyjson_mut_obj_add_null(doc, obj, "readOnly"); + + yyjson_mut_obj_add_strbuf(doc, obj, "revision", &dev->revision); } FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) @@ -229,6 +235,8 @@ void ffPrintPhysicalDiskHelpFormat(void) "Serial number", "Device kind (SSD or HDD)", "Device kind (Removable or Fixed)", + "Device kind (Read-only or Read-write)", + "Product revision", }); } From 91089a7fe9ec8a627b138ac95e2e9751420bac0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 25 Dec 2023 20:02:41 +0800 Subject: [PATCH 43/81] PhysicalDisk (Windows): init variables --- src/detection/physicaldisk/physicaldisk_windows.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index f1b47b908b..c8ffb748b1 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -65,6 +65,7 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic ffStrbufTrim(&device->serial, ' '); } + ffStrbufInit(&device->revision); if (sdd->ProductRevisionOffset != 0) { ffStrbufSetS(&device->revision, (const char*) sddBuffer + sdd->ProductRevisionOffset); From e672e40f8bb8380666255f152bb0ccb8302e1a30 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 26 Dec 2023 10:53:43 +0800 Subject: [PATCH 44/81] GPU: detect devices by OpenGL which works for asahi linux --- src/detection/gpu/gpu.c | 60 ++++++++++++++++++++++++++++++++--- src/detection/gpu/gpu_linux.c | 8 +++-- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 70980f5f94..ef423d7bee 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -1,6 +1,7 @@ #include "gpu.h" #include "detection/internal.h" #include "detection/vulkan/vulkan.h" +#include "detection/opengl/opengl.h" const char* FF_GPU_VENDOR_NAME_APPLE = "Apple"; const char* FF_GPU_VENDOR_NAME_AMD = "AMD"; @@ -46,17 +47,66 @@ const char* ffGetGPUVendorString(unsigned vendorId) return NULL; } +const char* detectByOpenGL(FFlist* gpus) +{ + FFOpenGLResult result; + ffStrbufInit(&result.version); + ffStrbufInit(&result.renderer); + ffStrbufInit(&result.vendor); + ffStrbufInit(&result.slv); + const char* error = ffDetectOpenGL(&instance.config.modules.openGL, &result); + if (!error) + { + FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); + gpu->type = FF_GPU_TYPE_UNKNOWN; + ffStrbufInitMove(&gpu->vendor, &result.vendor); + ffStrbufInitMove(&gpu->name, &result.renderer); + ffStrbufInit(&gpu->driver); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; + gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0}; + gpu->deviceId = 0; + + if (ffStrbufIgnCaseEqualS(&gpu->vendor, "Mesa")) + ffStrbufClear(&gpu->vendor); + + if (!gpu->vendor.length) + { + if (ffStrbufContainS(&result.renderer, "Apple")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); + else if (ffStrbufContainS(&result.renderer, "Intel")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if (ffStrbufContainS(&result.renderer, "AMD") || ffStrbufContainS(&result.renderer, "ATI")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + else if (ffStrbufContainS(&result.renderer, "NVIDIA")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + } + } + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.renderer); + ffStrbufDestroy(&result.vendor); + ffStrbufDestroy(&result.slv); + return error; +} + const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) { if (!options->forceVulkan) { const char* error = ffDetectGPUImpl(options, result); - if (!error) return NULL; + if (!error && result->length > 0) return NULL; } FFVulkanResult* vulkan = ffDetectVulkan(); - if (vulkan->error) return "GPU detection failed"; - ffListDestroy(result); - ffListInitMove(result, &vulkan->gpus); + if (!vulkan->error && vulkan->gpus.length > 0) + { + ffListDestroy(result); + ffListInitMove(result, &vulkan->gpus); + return NULL; + } + if (detectByOpenGL(result) == NULL) + return NULL; - return NULL; + return "GPU detection failed"; } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 4a170ead4c..a838269a40 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -46,12 +46,14 @@ static void pciDetectVendorName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* pci->ffpci_lookup_name(pci->access, gpu->vendor.chars, (int) gpu->vendor.allocated, PCI_LOOKUP_VENDOR, device->vendor_id); ffStrbufRecalculateLength(&gpu->vendor); - if(ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) + if(ffStrbufContainIgnCaseS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); - else if(ffStrbufContainS(&gpu->vendor, "Intel")) + else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Intel")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if(ffStrbufContainS(&gpu->vendor, "NVIDIA")) + else if(ffStrbufContainIgnCaseS(&gpu->vendor, "NVIDIA")) ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if(ffStrbufContainIgnCaseS(&gpu->vendor, "Apple")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); } static void drmDetectDeviceName(FFGPUResult* gpu, PCIData* pci, struct pci_dev* device) From dd3b3f22bac7d58ab15d21ed4c017820bb49330f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 26 Dec 2023 11:20:40 +0800 Subject: [PATCH 45/81] CPU (Linux): detect multi cpu models by lscpu Supports asahi linux --- src/detection/cpu/cpu_linux.c | 47 ++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 4b190cfc7e..05f5590cd9 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef __ANDROID__ #include "common/settings.h" @@ -171,10 +172,50 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (cpu->name.length == 0) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - if (!ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL })) + if (ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL }) == NULL) { - ffParsePropLines(buffer.chars, "Model name:", &cpu->name); - if (ffStrbufEqualS(&cpu->name, "-")) ffStrbufClear(&cpu->name); + char* pstart = buffer.chars; + while ((pstart = strstr(pstart, "Model name:"))) + { + pstart += strlen("Model name:"); + while (isspace(*pstart)) ++pstart; + if (*pstart == '\0') + break; + + if (cpu->name.length > 0) + ffStrbufAppendS(&cpu->name, " + "); + + char* pend = strchr(pstart, '\n'); + if (pend != NULL) + ffStrbufAppendNS(&cpu->name, (uint32_t) (pend - pstart), pstart); + else + { + ffStrbufAppendS(&cpu->name, pstart); + break; + } + + pstart = pend + 1; + } + + if (cpu->vendor.length == 0) + { + pstart = strstr(buffer.chars, "Vendor ID:"); + if (pstart) + { + pstart += strlen("Vendor ID:"); + while (isspace(*pstart)) ++pstart; + if (*pstart) + { + char* pend = strchr(pstart, '\n'); + if (pend != NULL) + ffStrbufAppendNS(&cpu->vendor, (uint32_t) (pend - pstart), pstart); + else + { + ffStrbufAppendS(&cpu->vendor, pstart); + } + } + } + } } } #endif From 60f5cc9079b603fbce47c06f036686ed5f86a1be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Dec 2023 13:32:55 +0800 Subject: [PATCH 46/81] CPU (Linux): don't print `-` --- src/detection/cpu/cpu_linux.c | 51 ++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 05f5590cd9..031db20ff5 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -168,13 +168,34 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectAndroid(cpu); #endif - #ifdef __linux__ if (cpu->name.length == 0) { FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); if (ffProcessAppendStdOut(&buffer, (char *const[]) { "lscpu", NULL }) == NULL) { char* pstart = buffer.chars; + + if (cpu->vendor.length == 0) + { + pstart = strstr(pstart, "Vendor ID:"); + if (pstart) + { + pstart += strlen("Vendor ID:"); + while (isspace(*pstart)) ++pstart; + if (*pstart) + { + char* pend = strchr(pstart, '\n'); + if (pend != NULL) + ffStrbufAppendNS(&cpu->vendor, (uint32_t) (pend - pstart), pstart); + else + { + ffStrbufAppendS(&cpu->vendor, pstart); + } + pstart = pend + 1; + } + } + } + while ((pstart = strstr(pstart, "Model name:"))) { pstart += strlen("Model name:"); @@ -185,6 +206,13 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (cpu->name.length > 0) ffStrbufAppendS(&cpu->name, " + "); + if (*pstart == '-') + { + ffStrbufAppendS(&cpu->name, "Unknown"); + ++pstart; + continue; + } + char* pend = strchr(pstart, '\n'); if (pend != NULL) ffStrbufAppendNS(&cpu->name, (uint32_t) (pend - pstart), pstart); @@ -196,29 +224,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) pstart = pend + 1; } - - if (cpu->vendor.length == 0) - { - pstart = strstr(buffer.chars, "Vendor ID:"); - if (pstart) - { - pstart += strlen("Vendor ID:"); - while (isspace(*pstart)) ++pstart; - if (*pstart) - { - char* pend = strchr(pstart, '\n'); - if (pend != NULL) - ffStrbufAppendNS(&cpu->vendor, (uint32_t) (pend - pstart), pstart); - else - { - ffStrbufAppendS(&cpu->vendor, pstart); - } - } - } - } } } - #endif return NULL; } From f319a80dc58e28836202a6e710702256dc5ac189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Dec 2023 13:40:41 +0800 Subject: [PATCH 47/81] CPU (Linux): if we failed to detect the number of physical cores, assume all logical cores are physical --- src/detection/cpu/cpu_linux.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 031db20ff5..8f33c491eb 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -133,10 +133,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) const char* error = parseCpuInfo(cpu, &physicalCoresBuffer, &cpuMHz, &cpuIsa, &cpuUarch); if (error) return error; - cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 1); - cpu->coresLogical = (uint16_t) get_nprocs_conf(); cpu->coresOnline = (uint16_t) get_nprocs(); + cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical); #define BP "/sys/devices/system/cpu/cpufreq/policy0/" if(ffPathExists(BP, FF_PATHTYPE_DIRECTORY)) From 16d34b6933fdc65f771b2c76a6429fa8e1ca4a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Dec 2023 15:50:48 +0800 Subject: [PATCH 48/81] Doc: update changelog --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d24f17423..8f3da617e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +# 2.4.1 + +Changes: +* `--gpu-use-nvml` has been renamed to `--gpu-driver-specific` due to using of `IGCL` and `AGS` +* We now detect external partitions more conservatively in Linux. USB partitions will not be detected as external always ( eg. The Linux kernel itself is installed in a USB drive ) + +Features: +* Support more authentication type detection for macOS Sonoma (Wifi, macOS) +* Default preset names to `.jsonc`. For example, `fastfetch -c all` will load `presets/all.jsonc` (#666) +* Use Intel Graphics Control Library (IGCL) to detect more GPU information. Windows only (GPU, Windows) +* Improve support of Asahi Linux (Brightness / CPU / GPU, Linux) +* Support more properties of physical disks (PhysicalDisk) + +Bugfixes: +* Fix Windows partition detection for WSL2 (Linux, Disk) +* Fix Btrfs subvolumes being detected as external partitions some times (Linux, Disk) +* Fix battery cycle counts in some places (Battery) + # 2.4.0 **We are deprecating flags based config files (will be removed in v3.0.0). We suggest you migrate to json based config files.** One may use `-c /path/to/config.conf --gen-config` to migrate existing flag based config files. From 5a372882fa5d6a0de18caa7d7916faca57bc6f42 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 26 Dec 2023 16:13:15 +0800 Subject: [PATCH 49/81] Battery (Linux): tidy --- src/detection/battery/battery_linux.c | 12 ++---------- src/modules/battery/battery.c | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 49daded722..113c8949cf 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -101,16 +101,8 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) { FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); - - if(options->dir.length > 0) - { - ffStrbufAppend(&baseDir, &options->dir); - ffStrbufEnsureEndsWithC(&baseDir, '/'); - } - else - { - ffStrbufAppendS(&baseDir, "/sys/class/power_supply/"); - } + ffStrbufAppend(&baseDir, &options->dir); + ffStrbufEnsureEndsWithC(&baseDir, '/'); uint32_t baseDirLength = baseDir.length; diff --git a/src/modules/battery/battery.c b/src/modules/battery/battery.c index c73897491f..0946ad0c03 100644 --- a/src/modules/battery/battery.c +++ b/src/modules/battery/battery.c @@ -258,7 +258,7 @@ void ffInitBatteryOptions(FFBatteryOptions* options) options->temp = false; #ifdef __linux__ - ffStrbufInit(&options->dir); + ffStrbufInitStatic(&options->dir, "/sys/class/power_supply/"); #elif defined(_WIN32) options->useSetupApi = false; #endif From b1f54ab7a206d20f086ad74faf403734efd554db Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 26 Dec 2023 16:43:44 +0800 Subject: [PATCH 50/81] Battery (Linux): fix temp detection for asahi --- src/detection/battery/battery_linux.c | 2 +- src/detection/temps/temps_linux.c | 15 +++++++++++++++ src/detection/temps/temps_linux.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 113c8949cf..04b8a9a0a9 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -89,7 +89,7 @@ static void parseBattery(FFstrbuf* dir, const char* id, FFBatteryOptions* option FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) { - if (ffStrbufEqualS(&value->name, id)) + if (ffStrbufEqualS(&value->deviceName, id)) { result->temperature = value->value; break; diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 5c8b390787..89d9f941ec 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -37,9 +37,24 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffReadFileBuffer(dir->chars, &valueBuffer); } ffStrbufTrimRightSpace(&valueBuffer); + ffStrbufSubstrBefore(dir, dirLength); if(valueBuffer.length) value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); + ffStrbufClear(&valueBuffer); + ffStrbufEnsureFree(&valueBuffer, 64); + ffStrbufAppendS(dir, "device"); + ssize_t linkLen = readlink(dir->chars, valueBuffer.chars, valueBuffer.allocated - 1); + if (linkLen > 0) + { + valueBuffer.length = (uint32_t) linkLen; + valueBuffer.chars[linkLen] = 0; + ffStrbufSubstrAfterLastC(&valueBuffer, '/'); + ffStrbufInitMove(&value->deviceName, &valueBuffer); + } + else + ffStrbufInit(&value->deviceName); + return value->name.length > 0 || value->deviceClass > 0; } diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h index 0d153ccfd8..ccb908b44b 100644 --- a/src/detection/temps/temps_linux.h +++ b/src/detection/temps/temps_linux.h @@ -5,6 +5,7 @@ typedef struct FFTempValue { FFstrbuf name; + FFstrbuf deviceName; uint32_t deviceClass; double value; } FFTempValue; From 0ee892f2de67c39fe4378c288c4d7b0dd969f776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Dec 2023 18:58:05 +0800 Subject: [PATCH 51/81] Disk (Linux): simplify impl of detecting partition removable --- src/detection/disk/disk_linux.c | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/detection/disk/disk_linux.c b/src/detection/disk/disk_linux.c index 69adbcea02..8adf748584 100644 --- a/src/detection/disk/disk_linux.c +++ b/src/detection/disk/disk_linux.c @@ -192,32 +192,19 @@ static bool isSubvolume(const FFlist* disks, FFDisk* currentDisk) static bool isRemovable(FFDisk* currentDisk) { - FF_STRBUF_AUTO_DESTROY basePath = ffStrbufCreateS("/sys/block/"); - - FF_AUTO_CLOSE_DIR DIR* dir = opendir(basePath.chars); - if(dir == NULL) + if (!ffStrbufStartsWithS(¤tDisk->mountFrom, "/dev/")) return false; - uint32_t index = ffStrbufLastIndexC(¤tDisk->mountFrom, '/'); - const char* partitionName = index == currentDisk->mountFrom.length ? NULL : currentDisk->mountFrom.chars + index + 1; - if (!partitionName || !*partitionName) return false; - - struct dirent* entry; - while((entry = readdir(dir)) != NULL) - { - if(entry->d_name[0] == '.') - continue; - - if (!ffStrStartsWith(partitionName, entry->d_name)) continue; + char sysBlockPartition[64]; + snprintf(sysBlockPartition, sizeof(sysBlockPartition), "/sys/class/block/%s", currentDisk->mountFrom.chars + strlen("/dev/")); - // /sys/block/sdx/removable - ffStrbufAppendS(&basePath, entry->d_name); - ffStrbufAppendS(&basePath, "/removable"); - char removableChar = '0'; - return ffReadFileData(basePath.chars, 1, &removableChar) > 0 && removableChar == '1'; - } + char sysBlockVolume[PATH_MAX]; // /sys/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda1 + if (realpath(sysBlockPartition, sysBlockVolume) == NULL) + return false; + strcpy(strrchr(sysBlockVolume, '/') + 1, "removable"); - return false; + char removableChar = '0'; + return ffReadFileData(sysBlockVolume, 1, &removableChar) > 0 && removableChar == '1'; } static void detectType(const FFlist* disks, FFDisk* currentDisk) From 0972eb698614ab91dcbc47e707f4074665b42b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 26 Dec 2023 19:23:26 +0800 Subject: [PATCH 52/81] PhysicalDisk: detect temp --- src/detection/physicaldisk/physicaldisk.h | 3 ++ .../physicaldisk/physicaldisk_apple.c | 1 + src/detection/physicaldisk/physicaldisk_bsd.c | 1 + .../physicaldisk/physicaldisk_linux.c | 16 +++++++++++ .../physicaldisk/physicaldisk_windows.c | 20 +++++++++++++ src/modules/physicaldisk/option.h | 1 + src/modules/physicaldisk/physicaldisk.c | 28 +++++++++++++++++++ 7 files changed, 70 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk.h b/src/detection/physicaldisk/physicaldisk.h index 15bb7ce511..76863f7834 100644 --- a/src/detection/physicaldisk/physicaldisk.h +++ b/src/detection/physicaldisk/physicaldisk.h @@ -1,5 +1,7 @@ #include "fastfetch.h" +#define FF_PHYSICALDISK_TEMP_UNSET (0/0.0) + typedef enum FFPhysicalDiskType { FF_PHYSICALDISK_TYPE_NONE = 0, @@ -24,6 +26,7 @@ typedef struct FFPhysicalDiskResult FFstrbuf revision; FFPhysicalDiskType type; uint64_t size; + double temperature; } FFPhysicalDiskResult; const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options); diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 85ffbbd250..2f7d1cc165 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -92,6 +92,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } } } + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; } return NULL; diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index 513d0f8e1e..a6920b887f 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -67,6 +67,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) type |= acw ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; device->type = type; + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; } geom_stats_snapshot_free(snap); diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 4a3a19227e..884339ca66 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -1,6 +1,7 @@ #include "physicaldisk.h" #include "common/io/io.h" #include "common/properties.h" +#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include @@ -129,6 +130,21 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (ffReadFileBuffer(pathSysBlock, &device->revision)) ffStrbufTrimRightSpace(&device->revision); } + + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; + if (options->temp) + { + const FFlist* tempsResult = ffDetectTemps(); + + FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) + { + if (ffStrStartsWith(devName, value->deviceName.chars)) // nvme0 - nvme0n1 + { + device->temperature = value->value; + break; + } + } + } } return NULL; diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index c8ffb748b1..e9d8f2e0ac 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -151,6 +151,26 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic device->size = (uint64_t) diskInfo->NumberMediaSides * diskInfo->TracksPerCylinder * diskInfo->SectorsPerTrack * diskInfo->BytesPerSector; } + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; + if (options->temp) + { + STORAGE_TEMPERATURE_DATA_DESCRIPTOR stdd = {}; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceTemperatureProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &stdd, + sizeof(stdd), + &retSize, + NULL + ) && retSize == sizeof(stdd)) + device->temperature = stdd.TemperatureInfo[0].Temperature; + } + return true; } diff --git a/src/modules/physicaldisk/option.h b/src/modules/physicaldisk/option.h index 243a98a6a5..f57770d677 100644 --- a/src/modules/physicaldisk/option.h +++ b/src/modules/physicaldisk/option.h @@ -10,4 +10,5 @@ typedef struct FFPhysicalDiskOptions FFModuleArgs moduleArgs; FFstrbuf namePrefix; + bool temp; } FFPhysicalDiskOptions; diff --git a/src/modules/physicaldisk/physicaldisk.c b/src/modules/physicaldisk/physicaldisk.c index 07be887587..864f5a6737 100644 --- a/src/modules/physicaldisk/physicaldisk.c +++ b/src/modules/physicaldisk/physicaldisk.c @@ -90,6 +90,14 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) } ffStrbufAppendC(&buffer, ']'); } + + if (dev->temperature == dev->temperature) //FF_PHYSICALDISK_TEMP_UNSET + { + if(buffer.length > 0) + ffStrbufAppendS(&buffer, " - "); + + ffParseTemperature(dev->temperature, &buffer); + } ffStrbufPutTo(&buffer, stdout); } else @@ -107,6 +115,7 @@ void ffPrintPhysicalDisk(FFPhysicalDiskOptions* options) {FF_FORMAT_ARG_TYPE_STRING, removableType}, {FF_FORMAT_ARG_TYPE_STRING, readOnlyType}, {FF_FORMAT_ARG_TYPE_STRBUF, &dev->revision}, + {FF_FORMAT_ARG_TYPE_DOUBLE, &dev->temperature}, }); } ++index; @@ -134,6 +143,12 @@ bool ffParsePhysicalDiskCommandOptions(FFPhysicalDiskOptions* options, const cha return true; } + if (ffStrEqualsIgnCase(subKey, "temp")) + { + options->temp = ffOptionParseBoolean(value); + return true; + } + return false; } @@ -156,6 +171,12 @@ void ffParsePhysicalDiskJsonObject(FFPhysicalDiskOptions* options, yyjson_val* m continue; } + if (ffStrEqualsIgnCase(key, "temp")) + { + options->temp = yyjson_get_bool(val); + continue; + } + ffPrintError(FF_PHYSICALDISK_MODULE_NAME, 0, &options->moduleArgs, "Unknown JSON key %s", key); } } @@ -169,6 +190,9 @@ void ffGeneratePhysicalDiskJsonConfig(FFPhysicalDiskOptions* options, yyjson_mut if (!ffStrbufEqual(&options->namePrefix, &defaultOptions.namePrefix)) yyjson_mut_obj_add_strbuf(doc, module, "namePrefix", &options->namePrefix); + + if (options->temp != defaultOptions.temp) + yyjson_mut_obj_add_bool(doc, module, "temp", options->temp); } void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) @@ -215,6 +239,8 @@ void ffGeneratePhysicalDiskJsonResult(FFPhysicalDiskOptions* options, yyjson_mut yyjson_mut_obj_add_null(doc, obj, "readOnly"); yyjson_mut_obj_add_strbuf(doc, obj, "revision", &dev->revision); + + yyjson_mut_obj_add_real(doc, obj, "temperature", dev->temperature); } FF_LIST_FOR_EACH(FFPhysicalDiskResult, dev, result) @@ -237,6 +263,7 @@ void ffPrintPhysicalDiskHelpFormat(void) "Device kind (Removable or Fixed)", "Device kind (Read-only or Read-write)", "Product revision", + "Device temperature", }); } @@ -256,6 +283,7 @@ void ffInitPhysicalDiskOptions(FFPhysicalDiskOptions* options) ffOptionInitModuleArg(&options->moduleArgs); ffStrbufInit(&options->namePrefix); + options->temp = false; } void ffDestroyPhysicalDiskOptions(FFPhysicalDiskOptions* options) From 17d6f84850458dfcb9b1cd3ba34e6d4fdeaf8037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Dec 2023 08:45:02 +0800 Subject: [PATCH 53/81] Temps (macOS): update sensors of M2X --- src/detection/temps/temps_apple.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index b274c49e0e..ba66c64330 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -323,14 +323,19 @@ const char *ffDetectCoreTemps(enum FFTempType type, double *result) break; case FF_TEMP_CPU_M2X: - count += detectTemp(conn, "Tp0A", result); // CPU core 1 - count += detectTemp(conn, "Tp0D", result); // CPU core 2 - count += detectTemp(conn, "Tp0E", result); // CPU core 3 - count += detectTemp(conn, "Tp01", result); // CPU core 4 - count += detectTemp(conn, "Tp02", result); // CPU core 5 - count += detectTemp(conn, "Tp05", result); // CPU core 6 - count += detectTemp(conn, "Tp06", result); // CPU core 7 - count += detectTemp(conn, "Tp09", result); // CPU core 8 + count += detectTemp(conn, "Tp1h", result); // CPU efficiency core 1 + count += detectTemp(conn, "Tp1t", result); // CPU efficiency core 2 + count += detectTemp(conn, "Tp1p", result); // CPU efficiency core 3 + count += detectTemp(conn, "Tp1l", result); // CPU efficiency core 4 + + count += detectTemp(conn, "Tp01", result); // CPU performance core 1 + count += detectTemp(conn, "Tp05", result); // CPU performance core 2 + count += detectTemp(conn, "Tp09", result); // CPU performance core 3 + count += detectTemp(conn, "Tp0D", result); // CPU performance core 4 + count += detectTemp(conn, "Tp0X", result); // CPU performance core 5 + count += detectTemp(conn, "Tp0b", result); // CPU performance core 6 + count += detectTemp(conn, "Tp0f", result); // CPU performance core 7 + count += detectTemp(conn, "Tp0j", result); // CPU performance core 8 break; case FF_TEMP_CPU_M3X: From 54bd4346ece36cc84e25b259296349bd354cc015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Dec 2023 08:46:49 +0800 Subject: [PATCH 54/81] Temps (macOS): rename functions --- src/detection/battery/battery_apple.c | 2 +- src/detection/cpu/cpu_apple.c | 8 ++++---- src/detection/gpu/gpu_apple.c | 12 ++++++------ src/detection/temps/temps_apple.c | 2 +- src/detection/temps/temps_apple.h | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 213cef8532..f301297f11 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -77,7 +77,7 @@ const char* ffDetectBattery(FFBatteryOptions* options, FFlist* results) if (!ffCfDictGetInt64(properties, CFSTR("Temperature"), &temp)) battery->temperature = (double) temp / 10 - 273.15; else - ffDetectCoreTemps(FF_TEMP_BATTERY, &battery->temperature); + ffDetectSmcTemps(FF_TEMP_BATTERY, &battery->temperature); } IOObjectRelease(registryEntry); diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index e75dbc1c88..a0afaa697a 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -11,14 +11,14 @@ static double detectCpuTemp(const FFstrbuf* cpuName) { switch (strtol(cpuName->chars + strlen("Apple M"), NULL, 10)) { - case 1: error = ffDetectCoreTemps(FF_TEMP_CPU_M1X, &result); break; - case 2: error = ffDetectCoreTemps(FF_TEMP_CPU_M2X, &result); break; - case 3: error = ffDetectCoreTemps(FF_TEMP_CPU_M3X, &result); break; + case 1: error = ffDetectSmcTemps(FF_TEMP_CPU_M1X, &result); break; + case 2: error = ffDetectSmcTemps(FF_TEMP_CPU_M2X, &result); break; + case 3: error = ffDetectSmcTemps(FF_TEMP_CPU_M3X, &result); break; default: error = "Unsupported Apple Silicon CPU"; } } else // PPC? - error = ffDetectCoreTemps(FF_TEMP_CPU_X64, &result); + error = ffDetectSmcTemps(FF_TEMP_CPU_X64, &result); if(error) return FF_CPU_TEMP_UNSET; diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index bed5586310..4b164bac2e 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -15,18 +15,18 @@ static double detectGpuTemp(const FFstrbuf* gpuName) { switch (strtol(gpuName->chars + strlen("Apple M"), NULL, 10)) { - case 1: error = ffDetectCoreTemps(FF_TEMP_GPU_M1X, &result); break; - case 2: error = ffDetectCoreTemps(FF_TEMP_GPU_M2X, &result); break; - case 3: error = ffDetectCoreTemps(FF_TEMP_GPU_M3X, &result); break; + case 1: error = ffDetectSmcTemps(FF_TEMP_GPU_M1X, &result); break; + case 2: error = ffDetectSmcTemps(FF_TEMP_GPU_M2X, &result); break; + case 3: error = ffDetectSmcTemps(FF_TEMP_GPU_M3X, &result); break; default: error = "Unsupported Apple Silicon GPU"; } } else if (ffStrbufStartsWithS(gpuName, "Intel")) - error = ffDetectCoreTemps(FF_TEMP_GPU_INTEL, &result); + error = ffDetectSmcTemps(FF_TEMP_GPU_INTEL, &result); else if (ffStrbufStartsWithS(gpuName, "Radeon") || ffStrbufStartsWithS(gpuName, "AMD")) - error = ffDetectCoreTemps(FF_TEMP_GPU_AMD, &result); + error = ffDetectSmcTemps(FF_TEMP_GPU_AMD, &result); else - error = ffDetectCoreTemps(FF_TEMP_GPU_UNKNOWN, &result); + error = ffDetectSmcTemps(FF_TEMP_GPU_UNKNOWN, &result); if (error) return FF_GPU_TEMP_UNSET; diff --git a/src/detection/temps/temps_apple.c b/src/detection/temps/temps_apple.c index ba66c64330..2fbc2ae094 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/detection/temps/temps_apple.c @@ -287,7 +287,7 @@ static bool detectTemp(io_connect_t conn, const char *sensor, double* sum) return true; } -const char *ffDetectCoreTemps(enum FFTempType type, double *result) +const char *ffDetectSmcTemps(enum FFTempType type, double *result) { static io_connect_t conn; static dispatch_once_t once_control; diff --git a/src/detection/temps/temps_apple.h b/src/detection/temps/temps_apple.h index ccf914311f..c04b41569d 100644 --- a/src/detection/temps/temps_apple.h +++ b/src/detection/temps/temps_apple.h @@ -29,4 +29,4 @@ enum FFTempType FF_TEMP_MEMORY, }; -const char *ffDetectCoreTemps(enum FFTempType type, double* result); +const char *ffDetectSmcTemps(enum FFTempType type, double* result); From 969a67ed0f9bc48ca131029b7b21259c815791c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Dec 2023 10:00:29 +0800 Subject: [PATCH 55/81] PhysicalDisk (macOS): detect temp --- .../physicaldisk/physicaldisk_apple.c | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 2f7d1cc165..faeaa3a595 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -7,6 +7,7 @@ #include #include #include +#include static inline void wrapIoObjectRelease(io_service_t* service) { @@ -16,6 +17,35 @@ static inline void wrapIoObjectRelease(io_service_t* service) } #define FF_IOOBJECT_AUTO_RELEASE __attribute__((__cleanup__(wrapIoObjectRelease))) +static inline void wrapIoDestroyPlugInInterface(IOCFPlugInInterface*** pluginInf) +{ + assert(pluginInf); + if (*pluginInf) + IODestroyPlugInInterface(*pluginInf); +} + +static const char* detectSsdTemp(io_service_t entryPhysical, double* temp) +{ + __attribute__((__cleanup__(wrapIoDestroyPlugInInterface))) IOCFPlugInInterface** pluginInf = NULL; + int32_t score; + if (IOCreatePlugInInterfaceForService(entryPhysical, kIONVMeSMARTUserClientTypeID, kIOCFPlugInInterfaceID, &pluginInf, &score) != kIOReturnSuccess) + return "IOCreatePlugInInterfaceForService() failed"; + + IONVMeSMARTInterface** smartInf = NULL; + if ((*pluginInf)->QueryInterface(pluginInf, CFUUIDGetUUIDBytes(kIONVMeSMARTInterfaceID), (LPVOID) &smartInf) != kIOReturnSuccess) + return "QueryInterface() failed"; + + NVMeSMARTData smartData; + const char* error = NULL; + if ((*smartInf)->SMARTReadData(smartInf, &smartData) == kIOReturnSuccess) + *temp = smartData.TEMPERATURE - 273; + else + error = "SMARTReadData() failed"; + + (*pluginInf)->Release(smartInf); + return error; +} + const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { FF_IOOBJECT_AUTO_RELEASE io_iterator_t iterator = 0; @@ -49,6 +79,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) ffStrbufInit(&device->interconnect); device->type = FF_PHYSICALDISK_TYPE_NONE; device->size = 0; + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; FF_CFTYPE_AUTO_RELEASE CFBooleanRef removable = IORegistryEntryCreateCFProperty(entryPartition, CFSTR(kIOMediaRemovableKey), kCFAllocatorDefault, kNilOptions); device->type |= CFBooleanGetValue(removable) ? FF_PHYSICALDISK_TYPE_REMOVABLE : FF_PHYSICALDISK_TYPE_FIXED; @@ -91,8 +122,14 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) device->type |= FF_PHYSICALDISK_TYPE_HDD; } } + + if (options->temp) + { + FF_CFTYPE_AUTO_RELEASE CFBooleanRef nvmeSMARTCapable = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyNVMeSMARTCapableKey), kCFAllocatorDefault, kNilOptions); + if (CFBooleanGetValue(nvmeSMARTCapable)) + detectSsdTemp(entryPhysical, &device->temperature); + } } - device->temperature = FF_PHYSICALDISK_TEMP_UNSET; } return NULL; From d5997b9f29f345a894f0b2ac2315a0291678f7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Dec 2023 10:16:33 +0800 Subject: [PATCH 56/81] Doc: document `--physicaldisk-temp` --- CHANGELOG.md | 1 + doc/json_schema.json | 5 +++++ src/data/help.json | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f3da617e7..c437f586e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Features: * Use Intel Graphics Control Library (IGCL) to detect more GPU information. Windows only (GPU, Windows) * Improve support of Asahi Linux (Brightness / CPU / GPU, Linux) * Support more properties of physical disks (PhysicalDisk) +* Support SSD temperature detection with `--physicaldisk-temp` (PhysicalDisk) Bugfixes: * Fix Windows partition detection for WSL2 (Linux, Disk) diff --git a/doc/json_schema.json b/doc/json_schema.json index 9da9dc902a..dd097dbe6f 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1381,6 +1381,11 @@ "description": "Show disks with given name prefix only", "type": "string" }, + "temp": { + "description": "Detect and display SSD temperature if supported", + "type": "boolean", + "default": false + }, "key": { "$ref": "#/$defs/key" }, diff --git a/src/data/help.json b/src/data/help.json index 946af06038..44f264caff 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -954,6 +954,15 @@ "type": "str" } }, + { + "long": "physicaldisk-temp", + "desc": "Detect and display SSD temperature if supported", + "arg": { + "type": "bool", + "optional": true, + "default": false + } + }, { "long": "bluetooth-show-disconnected", "desc": "Set if disconnected bluetooth devices should be printed", From 42694042f51499aa224ab2e28148c72867d6f694 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 27 Dec 2023 10:34:49 +0800 Subject: [PATCH 57/81] PhysicalDisk (FreeBSD): fix read-only type detection --- src/detection/physicaldisk/physicaldisk_bsd.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index a6920b887f..6b982bf3e2 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -43,6 +43,13 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) type |= ffStrEquals(ptr->lg_val, "0") ? FF_PHYSICALDISK_TYPE_SSD : FF_PHYSICALDISK_TYPE_HDD; else if (ffStrEquals(ptr->lg_name, "ident")) ffStrbufSetS(&identifier, ptr->lg_val); + else if (ffStrEquals(ptr->lg_name, "access")) + { + if (ffStrEquals(ptr->lg_val, "read-only")) + type |= FF_PHYSICALDISK_TYPE_READONLY; + else if (ffStrEquals(ptr->lg_val, "read-write")) + type |= FF_PHYSICALDISK_TYPE_READWRITE; + } } if (options->namePrefix.length && !ffStrbufStartsWith(&name, &options->namePrefix)) @@ -62,9 +69,12 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) device->size = (uint64_t) provider->lg_mediasize; ffStrbufInitMove(&device->name, &name); - int acr = 1, acw = 1; // TODO: find some documents to verify the usage - if (sscanf(provider->lg_mode, "r%dw%de%*d", &acr, &acw) == 2 && acr) - type |= acw ? FF_PHYSICALDISK_TYPE_READONLY : FF_PHYSICALDISK_TYPE_READWRITE; + if (!(device->type & FF_PHYSICALDISK_TYPE_READONLY) && !(device->type & FF_PHYSICALDISK_TYPE_READWRITE)) + { + int acr = 1, acw = 1; // Number of partitions mounted for reading or writing + if (sscanf(provider->lg_mode, "r%dw%de%*d", &acr, &acw) == 2 && acr) + type |= acw ? FF_PHYSICALDISK_TYPE_READWRITE : FF_PHYSICALDISK_TYPE_READONLY; + } device->type = type; device->temperature = FF_PHYSICALDISK_TEMP_UNSET; From 62647c3cb9ac5b29c8094adc4d9525ce70b68648 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 27 Dec 2023 11:14:15 +0800 Subject: [PATCH 58/81] PhysicalDisk (FreeBSD): add comments --- src/detection/physicaldisk/physicaldisk_bsd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index 6b982bf3e2..836e253904 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -32,6 +32,10 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (provider->lg_geom->lg_rank != 1) continue; + // Should memory disk (MD) be considered as physical disk? + //if (!ffStrEquals(provider->lg_geom->lg_class->lg_name, "DISK")) + // continue; + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(provider->lg_name); FF_STRBUF_AUTO_DESTROY identifier = ffStrbufCreate(); FFPhysicalDiskType type = FF_PHYSICALDISK_TYPE_NONE; From 6c4a4bfe13b47d3e0010e6773c24b81a2b209144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 27 Dec 2023 14:15:07 +0800 Subject: [PATCH 59/81] Disk (macOS): support name detection of iso volumes --- src/detection/disk/disk_bsd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index f885563d12..6f04ce37bd 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -26,10 +26,10 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) #include #include -struct VolAttrBuf { +struct CmnAttrBuf { uint32_t length; - attrreference_t volNameRef; - char volNameSpace[MAXPATHLEN]; + attrreference_t nameRef; + char nameSpace[NAME_MAX * 3 + 1]; } __attribute__((aligned(4), packed)); void detectFsInfo(struct statfs* fs, FFDisk* disk) @@ -41,12 +41,12 @@ void detectFsInfo(struct statfs* fs, FFDisk* disk) else disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; - struct VolAttrBuf attrBuf; + struct CmnAttrBuf attrBuf; if (getattrlist(disk->mountpoint.chars, &(struct attrlist) { .bitmapcount = ATTR_BIT_MAP_COUNT, - .volattr = ATTR_VOL_INFO | ATTR_VOL_NAME, + .commonattr = ATTR_CMN_NAME, }, &attrBuf, sizeof(attrBuf), 0) == 0) - ffStrbufInitNS(&disk->name, attrBuf.volNameRef.attr_length - 1 /* excluding '\0' */, attrBuf.volNameSpace); + ffStrbufInitNS(&disk->name, attrBuf.nameRef.attr_length - 1 /* excluding '\0' */, attrBuf.nameSpace); } #endif From 01fb4912898ee1b0c248b8fe471c95fcf0193824 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 27 Dec 2023 15:32:17 +0800 Subject: [PATCH 60/81] PhysicalDisk (FreeBSD): detect NVMe connect type --- src/detection/physicaldisk/physicaldisk_bsd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index 836e253904..8a8ec50f00 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -69,6 +69,9 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) case DEVSTAT_TYPE_IF_SCSI: ffStrbufAppendS(&device->interconnect, "SCSI"); break; case DEVSTAT_TYPE_IF_IDE: ffStrbufAppendS(&device->interconnect, "IDE"); break; case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break; + + // https://github.com/freebsd/freebsd-src/commit/d282baddb0b029ca8466d23ac51e95c918442535 + case 0x040 /*DEVSTAT_TYPE_IF_NVME*/: ffStrbufAppendS(&device->interconnect, "NVME"); break; } device->size = (uint64_t) provider->lg_mediasize; ffStrbufInitMove(&device->name, &name); From 73a30da7bc86cceef03fe4e67b8562dab6f20d12 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 27 Dec 2023 15:56:39 +0800 Subject: [PATCH 61/81] Disk (FreeBSD): detect partition name --- src/detection/disk/disk_bsd.c | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 6f04ce37bd..8584530e9c 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -5,6 +5,43 @@ #include #ifdef __FreeBSD__ +#include + +static const char* detectFsLabel(struct statfs* fs, FFDisk* disk) +{ + if (!ffStrStartsWith(fs->f_mntfromname, "/dev/")) + return "Only block devices are supported"; + + // Detect volume label in geom tree + static struct gmesh geomTree; + static struct gclass* cLabels; + if (!cLabels) + { + if (geomTree.lg_ident) + return "Previous geom_gettree() failed"; + + if (geom_gettree(&geomTree) < 0) + { + geomTree.lg_ident = (void*)(intptr_t)-1; + return "geom_gettree() failed"; + } + + for (cLabels = geomTree.lg_class.lh_first; !ffStrEquals(cLabels->lg_name, "LABEL"); cLabels = cLabels->lg_class.le_next); + if (!cLabels) + return "Class LABEL is not found"; + } + + for (struct ggeom* label = cLabels->lg_geom.lh_first; label; label = label->lg_geom.le_next) + { + struct gprovider* provider = label->lg_provider.lh_first; + if (!provider || !ffStrEquals(label->lg_name, fs->f_mntfromname + strlen("/dev/"))) continue; + const char* str = strchr(provider->lg_name, '/'); + ffStrbufSetS(&disk->name, str ? str + 1 : provider->lg_name); + } + + return NULL; +} + static void detectFsInfo(struct statfs* fs, FFDisk* disk) { if(ffStrbufEqualS(&disk->filesystem, "zfs")) @@ -19,6 +56,8 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) disk->type = FF_DISK_VOLUME_TYPE_EXTERNAL_BIT; else disk->type = FF_DISK_VOLUME_TYPE_REGULAR_BIT; + + detectFsLabel(fs, disk); } #elif __APPLE__ #include "util/apple/cf_helpers.h" From 12065bcfb0c51e262784a4b7587746565e85c62a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 28 Dec 2023 10:28:21 +0800 Subject: [PATCH 62/81] PhysicalDisk (Linux): display nvme namespace id if needed --- src/detection/diskio/diskio_linux.c | 18 ++++++++++++++++++ .../physicaldisk/physicaldisk_linux.c | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/detection/diskio/diskio_linux.c b/src/detection/diskio/diskio_linux.c index 4a84f25a55..5edf65901e 100644 --- a/src/detection/diskio/diskio_linux.c +++ b/src/detection/diskio/diskio_linux.c @@ -54,6 +54,24 @@ const char* ffDiskIOGetIoCounters(FFlist* result, FFDiskIOOptions* options) if (device->name.length == 0) ffStrbufSetS(&device->name, devName); + else if (ffStrStartsWith(devName, "nvme")) + { + int devid, nsid; + if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) + { + bool multiNs = nsid > 1; + if (!multiNs) + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/nvme%dn2", devName, devid); + multiNs = ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY); + } + if (multiNs) + { + // In Asahi Linux, there are multiple namespaces for the same NVMe drive. + ffStrbufAppendF(&device->name, " - %d", nsid); + } + } + } if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 884339ca66..c1d6b4bdc0 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -56,6 +56,24 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (device->name.length == 0) ffStrbufSetS(&device->name, devName); + else if (ffStrStartsWith(devName, "nvme")) + { + int devid, nsid; + if (sscanf(devName, "nvme%dn%d", &devid, &nsid) == 2) + { + bool multiNs = nsid > 1; + if (!multiNs) + { + snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/nvme%dn2", devName, devid); + multiNs = ffPathExists(pathSysBlock, FF_PATHTYPE_DIRECTORY); + } + if (multiNs) + { + // In Asahi Linux, there are multiple namespaces for the same NVMe drive. + ffStrbufAppendF(&device->name, " - %d", nsid); + } + } + } if (options->namePrefix.length && !ffStrbufStartsWith(&device->name, &options->namePrefix)) { From e5e70c1d928183a3d1ac1be9e75ce20cac085545 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 28 Dec 2023 10:31:28 +0800 Subject: [PATCH 63/81] PhysicalDisk (Linux): prettify interconnect type --- src/detection/physicaldisk/physicaldisk_linux.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index c1d6b4bdc0..f654017caf 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -88,11 +88,13 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { ffStrbufInit(&device->interconnect); if (strstr(pathSysDeviceReal, "/usb") != NULL) - ffStrbufSetS(&device->interconnect, "usb"); - else if (strstr(pathSysDeviceReal, "/ata") != NULL) - ffStrbufSetS(&device->interconnect, "ata"); + ffStrbufSetS(&device->interconnect, "USB"); else if (strstr(pathSysDeviceReal, "/nvme") != NULL) - ffStrbufSetS(&device->interconnect, "nvme"); + ffStrbufSetS(&device->interconnect, "NVMe"); + else if (strstr(pathSysDeviceReal, "/ata") != NULL) + ffStrbufSetS(&device->interconnect, "ATA"); + else if (strstr(pathSysDeviceReal, "/scsi") != NULL) + ffStrbufSetS(&device->interconnect, "SCSI"); else { snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/transport", devName); From 36bce8fb0eb7211060ae1fbc6b0fdb339e9a7a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Dec 2023 13:41:40 +0800 Subject: [PATCH 64/81] PhysicalDisk (macOS): fix a possible segfault --- src/detection/physicaldisk/physicaldisk_apple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index faeaa3a595..2964524311 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -126,7 +126,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (options->temp) { FF_CFTYPE_AUTO_RELEASE CFBooleanRef nvmeSMARTCapable = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyNVMeSMARTCapableKey), kCFAllocatorDefault, kNilOptions); - if (CFBooleanGetValue(nvmeSMARTCapable)) + if (nvmeSMARTCapable && CFBooleanGetValue(nvmeSMARTCapable)) detectSsdTemp(entryPhysical, &device->temperature); } } From 150e9fc650723b9339865888cc17d250993cffc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Dec 2023 13:47:21 +0800 Subject: [PATCH 65/81] PhysicalDisk: prettify interconnect type --- src/detection/physicaldisk/physicaldisk_bsd.c | 2 +- .../physicaldisk/physicaldisk_windows.c | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_bsd.c b/src/detection/physicaldisk/physicaldisk_bsd.c index 8a8ec50f00..99dbaf9cca 100644 --- a/src/detection/physicaldisk/physicaldisk_bsd.c +++ b/src/detection/physicaldisk/physicaldisk_bsd.c @@ -71,7 +71,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) case DEVSTAT_TYPE_IF_OTHER: ffStrbufAppendS(&device->interconnect, "OTHER"); break; // https://github.com/freebsd/freebsd-src/commit/d282baddb0b029ca8466d23ac51e95c918442535 - case 0x040 /*DEVSTAT_TYPE_IF_NVME*/: ffStrbufAppendS(&device->interconnect, "NVME"); break; + case 0x040 /*DEVSTAT_TYPE_IF_NVME*/: ffStrbufAppendS(&device->interconnect, "NVMe"); break; } device->size = (uint64_t) provider->lg_mediasize; ffStrbufInitMove(&device->name, &name); diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index e9d8f2e0ac..7246ad9a9d 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -78,25 +78,25 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic switch (sdd->BusType) { case BusTypeUnknown: ffStrbufSetStatic(&device->interconnect, "Unknown"); break; - case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "Scsi"); break; - case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "Atapi"); break; - case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "Ata"); break; + case BusTypeScsi: ffStrbufSetStatic(&device->interconnect, "SCSI"); break; + case BusTypeAtapi: ffStrbufSetStatic(&device->interconnect, "ATAPI"); break; + case BusTypeAta: ffStrbufSetStatic(&device->interconnect, "ATA"); break; case BusType1394: ffStrbufSetStatic(&device->interconnect, "1394"); break; - case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "Ssa"); break; - case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibra"); break; - case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "Usb"); break; + case BusTypeSsa: ffStrbufSetStatic(&device->interconnect, "SSA"); break; + case BusTypeFibre: ffStrbufSetStatic(&device->interconnect, "Fibre"); break; + case BusTypeUsb: ffStrbufSetStatic(&device->interconnect, "USB"); break; case BusTypeRAID: ffStrbufSetStatic(&device->interconnect, "RAID"); break; - case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iScsi"); break; - case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "Sas"); break; - case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "Sata"); break; - case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "Sd"); break; - case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "Mmc"); break; + case BusTypeiScsi: ffStrbufSetStatic(&device->interconnect, "iSCSI"); break; + case BusTypeSas: ffStrbufSetStatic(&device->interconnect, "SAS"); break; + case BusTypeSata: ffStrbufSetStatic(&device->interconnect, "SATA"); break; + case BusTypeSd: ffStrbufSetStatic(&device->interconnect, "SD"); break; + case BusTypeMmc: ffStrbufSetStatic(&device->interconnect, "MMC"); break; case BusTypeVirtual: ffStrbufSetStatic(&device->interconnect, "Virtual"); break; - case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "FileBackedVirtual"); break; + case BusTypeFileBackedVirtual: ffStrbufSetStatic(&device->interconnect, "File Backed Virtual"); break; case BusTypeSpaces: ffStrbufSetStatic(&device->interconnect, "Spaces"); break; - case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "Nvme"); break; + case BusTypeNvme: ffStrbufSetStatic(&device->interconnect, "NVMe"); break; case BusTypeSCM: ffStrbufSetStatic(&device->interconnect, "SCM"); break; - case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "Ufs"); break; + case BusTypeUfs: ffStrbufSetStatic(&device->interconnect, "UFS"); break; default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break; } From 4066c0d9e8614c64ccf010bdea48f324c9b94670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Dec 2023 14:50:39 +0800 Subject: [PATCH 66/81] PhysicalDisk (Windows): improve stability --- .../physicaldisk/physicaldisk_windows.c | 111 ++++++++++-------- 1 file changed, 65 insertions(+), 46 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_windows.c b/src/detection/physicaldisk/physicaldisk_windows.c index 7246ad9a9d..486f6aa181 100644 --- a/src/detection/physicaldisk/physicaldisk_windows.c +++ b/src/detection/physicaldisk/physicaldisk_windows.c @@ -100,55 +100,74 @@ static bool detectPhysicalDisk(const wchar_t* szDevice, FFlist* result, FFPhysic default: ffStrbufSetF(&device->interconnect, "Unknown (%d)", (int) sdd->BusType); break; } - DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; - if(DeviceIoControl( - hDevice, - IOCTL_STORAGE_QUERY_PROPERTY, - &(STORAGE_PROPERTY_QUERY) { - .PropertyId = StorageDeviceSeekPenaltyProperty, - .QueryType = PropertyStandardQuery, - }, - sizeof(STORAGE_PROPERTY_QUERY), - &dspd, - sizeof(dspd), - &retSize, - NULL - ) && retSize == sizeof(dspd)) - device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + { + DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {}; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &(STORAGE_PROPERTY_QUERY) { + .PropertyId = StorageDeviceSeekPenaltyProperty, + .QueryType = PropertyStandardQuery, + }, + sizeof(STORAGE_PROPERTY_QUERY), + &dspd, + sizeof(dspd), + &retSize, + NULL + ) && retSize == sizeof(dspd)) + device->type |= dspd.IncursSeekPenalty ? FF_PHYSICALDISK_TYPE_HDD : FF_PHYSICALDISK_TYPE_SSD; + } - DISK_GEOMETRY_EX dge = {}; - if(DeviceIoControl( - hDevice, - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, - NULL, - 0, - &dge, - sizeof(dge), - &retSize, - NULL)) - device->size = (uint64_t) dge.DiskSize.QuadPart; - else - device->size = 0; + { + DISK_GEOMETRY_EX dge = {}; + if(DeviceIoControl( + hDevice, + IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, + 0, + &dge, + sizeof(dge), + &retSize, + NULL)) + device->size = (uint64_t) dge.DiskSize.QuadPart; + else + device->size = 0; + } - GET_MEDIA_TYPES gmt = {}; - if(DeviceIoControl( - hDevice, - IOCTL_STORAGE_GET_MEDIA_TYPES_EX, - NULL, - 0, - &gmt, - sizeof(gmt), - &retSize, - NULL) && gmt.MediaInfoCount > 0 - ) { - __typeof__(gmt.MediaInfo[0].DeviceSpecific.DiskInfo)* diskInfo = &gmt.MediaInfo[0].DeviceSpecific.DiskInfo; - if (diskInfo->MediaCharacteristics & MEDIA_READ_ONLY) - device->type |= FF_PHYSICALDISK_TYPE_READONLY; - else if (diskInfo->MediaCharacteristics & MEDIA_READ_WRITE) - device->type |= FF_PHYSICALDISK_TYPE_READWRITE; - if (device->size == 0) - device->size = (uint64_t) diskInfo->NumberMediaSides * diskInfo->TracksPerCylinder * diskInfo->SectorsPerTrack * diskInfo->BytesPerSector; + uint8_t buffer[sizeof(GET_MEDIA_TYPES) + sizeof(DEVICE_MEDIA_INFO) * 7] = ""; + GET_MEDIA_TYPES* gmt = (GET_MEDIA_TYPES*) buffer; + if(DeviceIoControl( + hDevice, + IOCTL_STORAGE_GET_MEDIA_TYPES_EX, + NULL, + 0, + gmt, + sizeof(buffer), + &retSize, + NULL) && gmt->MediaInfoCount > 0 + ) + { + // DiskInfo and RemovableDiskInfo have the same structures. TapeInfo doesn't. + if (gmt->DeviceType != FILE_DEVICE_TAPE) + { + __typeof__(gmt->MediaInfo[0].DeviceSpecific.DiskInfo)* diskInfo = &gmt->MediaInfo[0].DeviceSpecific.DiskInfo; + if (diskInfo->MediaCharacteristics & MEDIA_READ_ONLY) + device->type |= FF_PHYSICALDISK_TYPE_READONLY; + else if (diskInfo->MediaCharacteristics & MEDIA_READ_WRITE) + device->type |= FF_PHYSICALDISK_TYPE_READWRITE; + if (device->size == 0) + device->size = (uint64_t) diskInfo->NumberMediaSides * diskInfo->TracksPerCylinder * diskInfo->SectorsPerTrack * diskInfo->BytesPerSector; + } + else + { + __typeof__(gmt->MediaInfo[0].DeviceSpecific.TapeInfo)* tapeInfo = &gmt->MediaInfo[0].DeviceSpecific.TapeInfo; + if (tapeInfo->MediaCharacteristics & MEDIA_READ_ONLY) + device->type |= FF_PHYSICALDISK_TYPE_READONLY; + else if (tapeInfo->MediaCharacteristics & MEDIA_READ_WRITE) + device->type |= FF_PHYSICALDISK_TYPE_READWRITE; + } + } } device->temperature = FF_PHYSICALDISK_TEMP_UNSET; From 6d50f1efddc0a864cb3b999cd841d354e5c3d5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Dec 2023 15:12:20 +0800 Subject: [PATCH 67/81] Doc: update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c437f586e1..0eac6d7a22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ Features: * Support more authentication type detection for macOS Sonoma (Wifi, macOS) * Default preset names to `.jsonc`. For example, `fastfetch -c all` will load `presets/all.jsonc` (#666) * Use Intel Graphics Control Library (IGCL) to detect more GPU information. Windows only (GPU, Windows) -* Improve support of Asahi Linux (Brightness / CPU / GPU, Linux) +* Improve support of Asahi Linux (Brightness / CPU / GPU / Disk, Linux) * Support more properties of physical disks (PhysicalDisk) * Support SSD temperature detection with `--physicaldisk-temp` (PhysicalDisk) +* Support partition label detection (Disk, FreeBSD) Bugfixes: * Fix Windows partition detection for WSL2 (Linux, Disk) From 0284f6bfd14c66ab7c6086686cca042b137ef210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 28 Dec 2023 15:42:07 +0800 Subject: [PATCH 68/81] Font: tidy --- src/common/font.c | 25 ++++++++++++++++++------- src/common/font.h | 6 +++++- src/util/FFstrbuf.c | 16 ---------------- src/util/FFstrbuf.h | 1 - 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/common/font.c b/src/common/font.c index 042fa74eee..b2f3547b8e 100644 --- a/src/common/font.c +++ b/src/common/font.c @@ -12,6 +12,22 @@ void ffFontInit(FFfont* font) ffListInit(&font->styles, sizeof(FFstrbuf)); } +static void strbufAppendNSExcludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude) +{ + if(value == NULL || length == 0) + return; + + ffStrbufEnsureFree(strbuf, length); + + for(uint32_t i = 0; i < length; i++) + { + if(value[i] != exclude) + strbuf->chars[strbuf->length++] = value[i]; + } + + strbuf->chars[strbuf->length] = '\0'; +} + static void fontInitPretty(FFfont* font) { ffStrbufAppend(&font->pretty, &font->name); @@ -155,7 +171,7 @@ static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* altern ffStrbufInit(alternativeBuffer); } - ffStrbufAppendNSExludingC(alternativeBuffer, wordLength, wordStart, '-'); + strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-'); if( strncasecmp(wordStart, "Ultra ", 6) == 0 || @@ -171,7 +187,7 @@ static void fontPangoParseWord(const char** data, FFfont* font, FFstrbuf* altern if(alternativeBuffer != NULL) { - ffStrbufAppendNSExludingC(alternativeBuffer, wordLength, wordStart, '-'); + strbufAppendNSExcludingC(alternativeBuffer, wordLength, wordStart, '-'); return; } @@ -200,11 +216,6 @@ void ffFontInitValues(FFfont* font, const char* name, const char* size) fontInitPretty(font); } -void ffFontInitCopy(FFfont* font, const char* name) -{ - ffFontInitValues(font, name, NULL); -} - void ffFontInitWithSpace(FFfont* font, const char* rawName) { const char* pspace = strrchr(rawName, ' '); diff --git a/src/common/font.h b/src/common/font.h index 5ececb2f6f..4ba4cfbbde 100644 --- a/src/common/font.h +++ b/src/common/font.h @@ -14,7 +14,11 @@ typedef struct FFfont void ffFontInit(FFfont* font); void ffFontInitQt(FFfont* font, const char* data); void ffFontInitPango(FFfont* font, const char* data); -void ffFontInitCopy(FFfont* font, const char* name); void ffFontInitValues(FFfont* font, const char* name, const char* size); void ffFontInitWithSpace(FFfont* font, const char* rawName); void ffFontDestroy(FFfont* font); + +static inline void ffFontInitCopy(FFfont* font, const char* name) +{ + ffFontInitValues(font, name, NULL); +} diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index 71e0b4d50d..703b4055dd 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -119,22 +119,6 @@ void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value) strbuf->chars[strbuf->length] = '\0'; } -void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude) -{ - if(value == NULL || length == 0) - return; - - ffStrbufEnsureFree(strbuf, length); - - for(uint32_t i = 0; i < length; i++) - { - if(value[i] != exclude) - strbuf->chars[strbuf->length++] = value[i]; - } - - strbuf->chars[strbuf->length] = '\0'; -} - void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int)) { if(value == NULL) diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index afdf74520d..df4a709519 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -41,7 +41,6 @@ static inline void ffStrbufAppend(FFstrbuf* __restrict strbuf, const FFstrbuf* _ void ffStrbufAppendC(FFstrbuf* strbuf, char c); void ffStrbufAppendNC(FFstrbuf* strbuf, uint32_t num, char c); void ffStrbufAppendNS(FFstrbuf* strbuf, uint32_t length, const char* value); -void ffStrbufAppendNSExludingC(FFstrbuf* strbuf, uint32_t length, const char* value, char exclude); void ffStrbufAppendTransformS(FFstrbuf* strbuf, const char* value, int(*transformFunc)(int)); FF_C_PRINTF(2, 3) void ffStrbufAppendF(FFstrbuf* strbuf, const char* format, ...); void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); From c1f511c8f2d7f9f4af80af040125665cda564577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 29 Dec 2023 15:12:41 +0800 Subject: [PATCH 69/81] GPU: detect supported platform graphic API version --- CMakeLists.txt | 2 + src/detection/gpu/gpu.c | 1 + src/detection/gpu/gpu.h | 1 + src/detection/gpu/gpu_apple.c | 6 ++ src/detection/gpu/gpu_apple.m | 40 ++++++++++ src/detection/gpu/gpu_linux.c | 2 + src/detection/gpu/gpu_windows.c | 7 ++ src/detection/vulkan/vulkan.c | 1 + src/modules/gpu/gpu.c | 7 +- src/util/windows/unicode.hpp | 5 ++ src/util/windows/variant.hpp | 137 ++++++++++++++++++++++++++++++++ src/util/windows/wmi.hpp | 137 +------------------------------- 12 files changed, 210 insertions(+), 136 deletions(-) create mode 100644 src/detection/gpu/gpu_apple.m create mode 100644 src/util/windows/variant.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a10d9449a..ab3b72a22f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -575,6 +575,7 @@ elseif(APPLE) src/detection/displayserver/displayserver_apple.c src/detection/font/font_apple.m src/detection/gpu/gpu_apple.c + src/detection/gpu/gpu_apple.m src/detection/host/host_apple.c src/detection/lm/lm_nosupport.c src/detection/icons/icons_nosupport.c @@ -905,6 +906,7 @@ elseif(APPLE) PRIVATE "-framework CoreWLAN" PRIVATE "-framework IOBluetooth" PRIVATE "-framework IOKit" + PRIVATE "-framework Metal" PRIVATE "-framework OpenGL" PRIVATE "-framework OpenCL" PRIVATE "-framework SystemConfiguration" diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index ef423d7bee..3fd82ca6b9 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -62,6 +62,7 @@ const char* detectByOpenGL(FFlist* gpus) ffStrbufInitMove(&gpu->vendor, &result.vendor); ffStrbufInitMove(&gpu->name, &result.renderer); ffStrbufInit(&gpu->driver); + ffStrbufInitF(&gpu->platformApi, "OpenGL %s", result.version.chars); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 23ebcc7f24..440d175d73 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -29,6 +29,7 @@ typedef struct FFGPUResult FFstrbuf vendor; FFstrbuf name; FFstrbuf driver; + FFstrbuf platformApi; double temperature; int32_t coreCount; double frequency; // Real time clock frequency in GHz diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 4b164bac2e..b7db8c562d 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -6,6 +6,8 @@ #include +const char* ffGpuDetectMetal(FFlist* gpus); + static double detectGpuTemp(const FFstrbuf* gpuName) { double result = 0; @@ -55,6 +57,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + IORegistryEntryGetRegistryEntryID(registryEntry, &gpu->deviceId); + ffStrbufInitStatic(&gpu->platformApi, "Metal"); ffStrbufInit(&gpu->driver); // Ok for both Apple and Intel ffCfDictGetString(properties, CFSTR("CFBundleIdentifier"), &gpu->driver); @@ -103,5 +107,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) } IOObjectRelease(iterator); + + ffGpuDetectMetal(gpus); return NULL; } diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m new file mode 100644 index 0000000000..1079ff1e03 --- /dev/null +++ b/src/detection/gpu/gpu_apple.m @@ -0,0 +1,40 @@ +#include "gpu.h" + +#import + +#ifndef MAC_OS_VERSION_13_0 + #define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001) +#endif + +const char* ffGpuDetectMetal(FFlist* gpus) +{ + if (@available(macOS 10.15, *)) + { + for (id device in MTLCopyAllDevices()) + { + FFGPUResult* gpu = NULL; + FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) + { + if (x->deviceId == device.registryID || ffStrbufEqualS(&x->name, device.name.UTF8String)) + { + gpu = x; + break; + } + } + if (!gpu) continue; + + if ([device supportsFamily:MTLGPUFamilyMetal3]) + ffStrbufSetStatic(&gpu->platformApi, "Metal 3"); + else if ([device supportsFamily:MTLGPUFamilyCommon3]) + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 3"); + else if ([device supportsFamily:MTLGPUFamilyCommon2]) + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 2"); + else if ([device supportsFamily:MTLGPUFamilyCommon1]) + ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); + + gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + } + } + + return NULL; +} diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index a838269a40..1a7a196079 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -221,6 +221,8 @@ static void pciHandleDevice(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* FFGPUResult* gpu = ffListAdd(results); + ffStrbufInit(&gpu->platformApi); + ffStrbufInit(&gpu->vendor); pciDetectVendorName(gpu, pci, device); diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index db8e593792..b4ddadd460 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -74,6 +74,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->vendor); ffStrbufInitWS(&gpu->name, displayDevice.DeviceString); ffStrbufInit(&gpu->driver); + ffStrbufInitStatic(&gpu->platformApi, "Direct3D"); gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; @@ -114,6 +115,12 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); + + uint32_t featureLevel = 0; + if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 12.%u", (featureLevel & 0x0F00) >> 8); + else if(ffRegReadUint(hDirectxKey, L"MaxD3D11FeatureLevel", &featureLevel, NULL) && featureLevel) + ffStrbufSetF(&gpu->platformApi, "Direct3D 11.%u", (featureLevel & 0x0F00) >> 8); } else if (!ffRegReadUint64(hKey, L"HardwareInformation.qwMemorySize", &gpu->dedicated.total, NULL)) { diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 5d7fe431b0..6331f7d709 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -181,6 +181,7 @@ static const char* detectVulkan(FFVulkanResult* result) FFGPUResult* gpu = ffListAdd(&result->gpus); + ffStrbufInitF(&gpu->platformApi, "Vulkan %u.%u.%u", deviceAPIVersion.major, deviceAPIVersion.minor, deviceAPIVersion.patch); gpu->deviceId = physicalDeviceProperties.properties.deviceID; ffStrbufInitS(&gpu->name, physicalDeviceProperties.properties.deviceName); diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index a3360ad966..7646ad5bd5 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -9,7 +9,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 11 +#define FF_GPU_NUM_FORMAT_ARGS 12 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -83,6 +83,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu {FF_FORMAT_ARG_TYPE_UINT64, &gpu->dedicated.used}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.total}, {FF_FORMAT_ARG_TYPE_UINT64, &gpu->shared.used}, + {FF_FORMAT_ARG_TYPE_STRBUF, &gpu->platformApi}, {FF_FORMAT_ARG_TYPE_DOUBLE, &gpu->frequency}, }); } @@ -309,6 +310,8 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &gpu->vendor); + yyjson_mut_obj_add_strbuf(doc, obj, "platformApi", &gpu->platformApi); + if (gpu->frequency == FF_GPU_FREQUENCY_UNSET) yyjson_mut_obj_add_null(doc, obj, "frequency"); else @@ -336,6 +339,8 @@ void ffPrintGPUHelpFormat(void) "GPU used dedicated memory", "GPU total shared memory", "GPU used shared memory", + "The platform API that GPU supports", + "Current frequency in GHz", }); } diff --git a/src/util/windows/unicode.hpp b/src/util/windows/unicode.hpp index 18441a50da..b6745572bb 100644 --- a/src/util/windows/unicode.hpp +++ b/src/util/windows/unicode.hpp @@ -11,6 +11,11 @@ extern "C" { #include +static inline void ffStrbufInitWSV(FFstrbuf* result, const std::wstring_view source) +{ + return ffStrbufInitNWS(result, (uint32_t) source.size(), source.data()); +} + static inline void ffStrbufSetWSV(FFstrbuf* result, const std::wstring_view source) { return ffStrbufSetNWS(result, (uint32_t) source.size(), source.data()); diff --git a/src/util/windows/variant.hpp b/src/util/windows/variant.hpp new file mode 100644 index 0000000000..8181bd776c --- /dev/null +++ b/src/util/windows/variant.hpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include + +struct FFWmiVariant: VARIANT +{ + explicit FFWmiVariant() { VariantInit(this); } + ~FFWmiVariant() { VariantClear(this); } + + FFWmiVariant(const FFWmiVariant&) = delete; + FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization + + bool hasValue() { + return this->vt != VT_EMPTY; + } + + explicit operator bool() { + return this->hasValue(); + } + + template T get() + { + // boolean + if constexpr (std::is_same_v) { + assert(this->vt == VT_BOOL); + return this->boolVal != VARIANT_FALSE; + } + + // signed + else if constexpr (std::is_same_v) { + assert(this->vt == VT_I1); + return this->cVal; + } + else if constexpr (std::is_same_v) { + assert(vt == VT_I2); + return this->iVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_I4 || vt == VT_INT); + return this->intVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_I8); + return this->llVal; + } + + // unsigned + else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI1); + return this->bVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI2); + return this->uiVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI4 || vt == VT_UINT); + return this->uintVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_UI8); + return this->ullVal; + } + + // decimal + else if constexpr (std::is_same_v) { + assert(this->vt == VT_R4); + return this->fltVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_R8); + return this->dblVal; + } + + // string + else if constexpr (std::is_same_v) { + assert(this->vt == VT_LPSTR); + return this->pcVal; + } + else if constexpr (std::is_same_v) { + assert(this->vt == VT_BSTR || this->vt == VT_LPWSTR); + if (this->vt == VT_LPWSTR) + return this->bstrVal; + else + return { this->bstrVal, SysStringLen(this->bstrVal) }; + } + + // array signed + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I1); + return std::make_pair((int8_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I2); + return std::make_pair((int16_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I4); + return std::make_pair((int32_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_I8); + return std::make_pair((int64_t*)this->parray->pvData, this->parray->cDims); + } + + // array unsigned + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI1); + return std::make_pair((uint8_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI2); + return std::make_pair((uint16_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI4); + return std::make_pair((uint32_t*)this->parray->pvData, this->parray->cDims); + } + else if constexpr (std::is_same_v>) { + assert(this->vt & VT_ARRAY); + assert((this->vt & ~VT_ARRAY) == VT_UI8); + return std::make_pair((uint64_t*)this->parray->pvData, this->parray->cDims); + } + else { + assert(false && "unsupported type"); + __builtin_unreachable(); + } + } +}; diff --git a/src/util/windows/wmi.hpp b/src/util/windows/wmi.hpp index 561f1ff5ed..f9e3e9ae3a 100644 --- a/src/util/windows/wmi.hpp +++ b/src/util/windows/wmi.hpp @@ -8,10 +8,9 @@ extern "C" { #include #include -#include -#include #include -#include + +#include "variant.hpp" enum class FFWmiNamespace { CIMV2, @@ -19,138 +18,6 @@ enum class FFWmiNamespace { LAST, }; -struct FFWmiVariant: VARIANT { - explicit FFWmiVariant() { VariantInit(this); } - ~FFWmiVariant() { VariantClear(this); } - - FFWmiVariant(const FFWmiVariant&) = delete; - FFWmiVariant(FFWmiVariant&&); // don't define it to enforce NRVO optimization - - bool hasValue() { - return this->vt != VT_EMPTY; - } - - explicit operator bool() { - return this->hasValue(); - } - - template T get() - { - // boolean - if constexpr (std::is_same_v) { - assert(this->vt == VT_BOOL); - return this->boolVal != VARIANT_FALSE; - } - - // signed - else if constexpr (std::is_same_v) { - assert(this->vt == VT_I1); - return this->cVal; - } - else if constexpr (std::is_same_v) { - assert(vt == VT_I2); - return this->iVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_I4 || vt == VT_INT); - return this->intVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_I8); - return this->llVal; - } - - // unsigned - else if constexpr (std::is_same_v) { - assert(this->vt == VT_UI1); - return this->bVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_UI2); - return this->uiVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_UI4 || vt == VT_UINT); - return this->uintVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_UI8); - return this->ullVal; - } - - // decimal - else if constexpr (std::is_same_v) { - assert(this->vt == VT_R4); - return this->fltVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_R8); - return this->dblVal; - } - - // string - else if constexpr (std::is_same_v) { - assert(this->vt == VT_LPSTR); - return this->pcVal; - } - else if constexpr (std::is_same_v) { - assert(this->vt == VT_BSTR || this->vt == VT_LPWSTR); - if (this->vt == VT_LPWSTR) - return this->bstrVal; - else - return { this->bstrVal, SysStringLen(this->bstrVal) }; - } - - // array signed - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_I1); - return std::make_pair((int8_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_I2); - return std::make_pair((int16_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_I4); - return std::make_pair((int32_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_I8); - return std::make_pair((int64_t*)this->parray->pvData, this->parray->cDims); - } - - // array unsigned - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_UI1); - return std::make_pair((uint8_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_UI2); - return std::make_pair((uint16_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_UI4); - return std::make_pair((uint32_t*)this->parray->pvData, this->parray->cDims); - } - else if constexpr (std::is_same_v>) { - assert(this->vt & VT_ARRAY); - assert((this->vt & ~VT_ARRAY) == VT_UI8); - return std::make_pair((uint64_t*)this->parray->pvData, this->parray->cDims); - } - else { - assert(false && "unsupported type"); - __builtin_unreachable(); - } - } -}; - struct FFWmiRecord { IWbemClassObject* obj; From ef1d102e0552d653aee86c40b161cdd007019f60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 29 Dec 2023 23:00:50 +0800 Subject: [PATCH 70/81] GPU (Windows): clean up vendor name --- src/detection/gpu/gpu_windows.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index b4ddadd460..719d98a509 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -70,8 +70,13 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (ffListContains(gpus, &gpuName, (void*) isGpuNameEqual)) continue; } + // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html + // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" + uint32_t vendorId = 0, deviceId = 0, subSystemId = 0, revId = 0; + swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId); + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - ffStrbufInit(&gpu->vendor); + ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); ffStrbufInitWS(&gpu->name, displayDevice.DeviceString); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "Direct3D"); @@ -89,14 +94,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regControlVideoKey, &hKey, NULL)) continue; ffRegReadStrbuf(hKey, L"DriverVersion", &gpu->driver, NULL); - ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL); - - if (ffStrbufContainS(&gpu->vendor, "Intel")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); - else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); - else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) - ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); wmemcpy(regDirectxKey + regDirectxKeyPrefixLength, displayDevice.DeviceKey + deviceKeyPrefixLength, strlen("00000000-0000-0000-0000-000000000000}")); FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; @@ -129,6 +126,17 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->dedicated.total = vmem; gpu->type = gpu->dedicated.total > 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; } + + if (gpu->vendor.length == 0) + { + ffRegReadStrbuf(hKey, L"ProviderName", &gpu->vendor, NULL); + if (ffStrbufContainS(&gpu->vendor, "Intel")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL); + else if (ffStrbufContainS(&gpu->vendor, "NVIDIA")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA); + else if (ffStrbufContainS(&gpu->vendor, "AMD") || ffStrbufContainS(&gpu->vendor, "ATI")) + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD); + } } __typeof__(&ffDetectNvidiaGpuInfo) detectFn; @@ -136,10 +144,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (getDriverSpecificDetectionFn(gpu->vendor.chars, &detectFn, &dllName) && (options->temp || options->driverSpecific)) { - uint32_t vendorId, deviceId, subSystemId, revId; - // See: https://download.nvidia.com/XFree86/Linux-x86_64/545.23.06/README/supportedchips.html - // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" - if (swscanf(displayDevice.DeviceID, L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x", &vendorId, &deviceId, &subSystemId, &revId) == 4) + if (vendorId && deviceId && subSystemId && revId) { detectFn( &(FFGpuDriverCondition) { From 0707902532e974e8c69061f729fd831503b53352 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 29 Dec 2023 23:33:16 +0800 Subject: [PATCH 71/81] PhysicalDisk (Apple): trim strings --- src/detection/physicaldisk/physicaldisk_apple.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 2964524311..4fbc849513 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -111,7 +111,9 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) if (deviceCharacteristics) { ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductSerialNumberKey), &device->serial); + ffStrbufTrim(&device->serial, ' '); ffCfDictGetString(deviceCharacteristics, CFSTR(kIOPropertyProductRevisionLevelKey), &device->revision); + ffStrbufTrim(&device->revision, ' '); CFStringRef mediumType = (CFStringRef) CFDictionaryGetValue(deviceCharacteristics, CFSTR(kIOPropertyMediumTypeKey)); if (mediumType) From bce96cf3f0264235574e8c6805381ec1d774115b Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 29 Dec 2023 23:35:47 +0800 Subject: [PATCH 72/81] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eac6d7a22..f52a3bdad1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Features: * Support more properties of physical disks (PhysicalDisk) * Support SSD temperature detection with `--physicaldisk-temp` (PhysicalDisk) * Support partition label detection (Disk, FreeBSD) +* Support platform specific graphic API version detection (GPU, macOS / Windows) Bugfixes: * Fix Windows partition detection for WSL2 (Linux, Disk) From db6d5d7fd66b3094f26cf9f0bc5295f13a36edbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Dec 2023 14:19:25 +0800 Subject: [PATCH 73/81] Windows: get rid of `InitOnceExecuteOnce` --- src/common/networking_windows.c | 45 +++++++++++++++-------------- src/util/windows/com.cpp | 19 +++++------- src/util/windows/wmi.cpp | 51 +++++++++++++++------------------ 3 files changed, 54 insertions(+), 61 deletions(-) diff --git a/src/common/networking_windows.c b/src/common/networking_windows.c index 4cb0e1d1a3..739b27600f 100644 --- a/src/common/networking_windows.c +++ b/src/common/networking_windows.c @@ -7,22 +7,18 @@ static LPFN_CONNECTEX ConnectEx; -static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context) +static const char* initWsaData(WSADATA* wsaData) { - (void)once; - (void)param; - static WSADATA wsaData; - *context = &wsaData; - if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) - return FALSE; + if(WSAStartup(MAKEWORD(2, 2), wsaData) != 0) + return "WSAStartup() failed"; - if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) - return FALSE; + if(LOBYTE(wsaData->wVersion) != 2 || HIBYTE(wsaData->wVersion) != 2) + return "Invalid wsaData version found"; //Dummy socket needed for WSAIoctl SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0); if(sockfd == INVALID_SOCKET) - return FALSE; + return "socket(AF_INET, SOCK_STREAM) failed"; DWORD dwBytes; GUID guid = WSAID_CONNECTEX; @@ -30,28 +26,35 @@ static BOOL WINAPI initWsaData(PINIT_ONCE once, PVOID param, PVOID* context) &guid, sizeof(guid), &ConnectEx, sizeof(ConnectEx), &dwBytes, NULL, NULL) != 0) - return FALSE; + return "WSAIoctl(sockfd, SIO_GET_EXTENSION_FUNCTION_POINTER) failed"; + + closesocket(sockfd); - return closesocket(sockfd) == 0; + return NULL; } bool ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, const char* path, const char* headers) { - static INIT_ONCE once = INIT_ONCE_STATIC_INIT; - WSADATA* pData; - if(!InitOnceExecuteOnce(&once, initWsaData, NULL, (LPVOID*) &pData)) + static WSADATA wsaData; + if (wsaData.wVersion == 0) + { + if (initWsaData(&wsaData) != NULL) + { + wsaData.wVersion = (WORD) -1; + return false; + } + } + else if (wsaData.wVersion == (WORD) -1) return false; memset(state, 0, sizeof(*state)); - struct addrinfo hints = { - .ai_family = AF_INET, - .ai_socktype = SOCK_STREAM, - }; - struct addrinfo* addr; - if(getaddrinfo(host, "80", &hints, &addr) != 0) + if(getaddrinfo(host, "80", &(struct addrinfo) { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &addr) != 0) return false; state->sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); diff --git a/src/util/windows/com.cpp b/src/util/windows/com.cpp index 43c4a5a496..f1e43418c0 100644 --- a/src/util/windows/com.cpp +++ b/src/util/windows/com.cpp @@ -2,7 +2,6 @@ #include "fastfetch.h" #include -#include //https://learn.microsoft.com/en-us/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer //https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/computer-system-hardware-classes @@ -11,14 +10,11 @@ static void CoUninitializeWrap(void) CoUninitialize(); } -static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, FF_MAYBE_UNUSED PVOID lpParameter, PVOID* lpContext) +static const char* doInitCom() { // Initialize COM if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) - { - *lpContext = (PVOID) "CoInitializeEx() failed"; - return FALSE; - } + return "CoInitializeEx() failed"; // Set general COM security levels if (FAILED(CoInitializeSecurity( @@ -34,18 +30,17 @@ static BOOL CALLBACK InitHandleFunction(FF_MAYBE_UNUSED PINIT_ONCE lpInitOnce, F ))) { CoUninitialize(); - *lpContext = (PVOID) "CoInitializeSecurity() failed"; - return FALSE; + return "CoInitializeSecurity() failed"; } atexit(CoUninitializeWrap); - return TRUE; + return NULL; } const char* ffInitCom(void) { - const char* error = NULL; - static INIT_ONCE s_InitOnce; - InitOnceExecuteOnce(&s_InitOnce, &InitHandleFunction, NULL, (void**)&error); + static const char* error = ""; + if (error && error[0] == '\0') + error = doInitCom(); return error; } diff --git a/src/util/windows/wmi.cpp b/src/util/windows/wmi.cpp index a131bceb51..6e8db9615e 100644 --- a/src/util/windows/wmi.cpp +++ b/src/util/windows/wmi.cpp @@ -21,7 +21,7 @@ namespace }; } -static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lpContext) +static const char* doInitService(const wchar_t* networkResource, IWbemServices** result) { HRESULT hres; @@ -35,10 +35,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp (LPVOID*) &pLoc); if (FAILED(hres)) - { - *((const char**)lpContext) = "Failed to create IWbemLocator object"; - return FALSE; - } + return "Failed to create IWbemLocator object"; // Connect to WMI through the IWbemLocator::ConnectServer method IWbemServices* pSvc = nullptr; @@ -47,7 +44,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp // the current user and obtain pointer pSvc // to make IWbemServices calls. hres = pLoc->ConnectServer( - bstr_t((const wchar_t*) lpParameter), // Object path of WMI namespace + bstr_t(networkResource), // Object path of WMI namespace nullptr, // User name. nullptr = current user nullptr, // User password. nullptr = current 0, // Locale. nullptr indicates current @@ -60,10 +57,7 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp pLoc = nullptr; if (FAILED(hres)) - { - *((const char**)lpContext) = "Could not connect WMI server"; - return FALSE; - } + return "Could not connect WMI server"; // Set security levels on the proxy ------------------------- hres = CoSetProxyBlanket( @@ -80,39 +74,40 @@ static BOOL CALLBACK InitHandleFunction(PINIT_ONCE, PVOID lpParameter, PVOID* lp if (FAILED(hres)) { pSvc->Release(); - *((const char**)lpContext) = "Could not set proxy blanket"; - return FALSE; + return "Could not set proxy blanket"; } - *((IWbemServices**)lpContext) = pSvc; - return TRUE; + *result = pSvc; + return NULL; } FFWmiQuery::FFWmiQuery(const wchar_t* queryStr, FFstrbuf* error, FFWmiNamespace wmiNs) : pEnumerator(nullptr) { - const char* context = ffInitCom(); - if (context) + const char* errStr; + if ((errStr = ffInitCom())) { if (error) - ffStrbufAppendS(error, context); + ffStrbufSetS(error, errStr); return; } - static INIT_ONCE s_InitOnce[(int) FFWmiNamespace::LAST] = {}; - if (InitOnceExecuteOnce( - &s_InitOnce[(int)wmiNs], - &InitHandleFunction, - (PVOID) (wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI"), - (void**)&context) == FALSE - ) { - if(error) - ffStrbufAppendS(error, context); - return; + static IWbemServices* contexts[(int) FFWmiNamespace::LAST]; + + IWbemServices* context = contexts[(int)wmiNs]; + if (!contexts[(int)wmiNs]) + { + if ((errStr = doInitService(wmiNs == FFWmiNamespace::CIMV2 ? L"ROOT\\CIMV2" : L"ROOT\\WMI", &context))) + { + if (error) + ffStrbufSetS(error, errStr); + return; + } + contexts[(int)wmiNs] = context; } // Use the IWbemServices pointer to make requests of WMI - HRESULT hres = ((IWbemServices*)context)->ExecQuery( + HRESULT hres = context->ExecQuery( bstr_t(L"WQL"), bstr_t(queryStr), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, From adae31304dd27221fdc046022e137df2eee2f8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Dec 2023 14:21:52 +0800 Subject: [PATCH 74/81] Media (macOS): tidy --- src/detection/media/media_apple.m | 1 - 1 file changed, 1 deletion(-) diff --git a/src/detection/media/media_apple.m b/src/detection/media/media_apple.m index 7413012736..0edd702647 100644 --- a/src/detection/media/media_apple.m +++ b/src/detection/media/media_apple.m @@ -79,7 +79,6 @@ void ffDetectMediaImpl(FFMediaResult* media) { - FF_UNUSED(instance) const char* error = getMedia(media); ffStrbufAppendS(&media->error, error); } From 275b53c6c06ebcb19a793c65ad50e56109852687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Dec 2023 18:12:21 +0800 Subject: [PATCH 75/81] Vulkan: don't print software renderers --- src/detection/vulkan/vulkan.c | 40 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 6331f7d709..70d6c55906 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -141,10 +141,14 @@ static const char* detectVulkan(FFVulkanResult* result) else ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties.properties); + + //We don't want software rasterizers to show up as physical gpu + if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) + continue; + //If the device api version is higher than the current highest device api version, overwrite it //In this case, also use the current device driver name as the shown driver name - FFVersion deviceAPIVersion = FF_VERSION_INIT; applyVulkanVersion(physicalDeviceProperties.properties.apiVersion, &deviceAPIVersion); if(ffVersionCompare(&deviceAPIVersion, &maxDeviceApiVersion) > 0) @@ -168,10 +172,6 @@ static const char* detectVulkan(FFVulkanResult* result) //Add the device to the list of devices shown by the GPU module - //We don't want software rasterizers to show up as physical gpu - if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU) - continue; - // #456 FF_LIST_FOR_EACH(FFGPUResult, gpu, result->gpus) { @@ -230,22 +230,20 @@ static const char* detectVulkan(FFVulkanResult* result) FFVulkanResult* ffDetectVulkan(void) { static FFVulkanResult result; - static bool init = false; - - if(init) - return &result; - init = true; - - ffStrbufInit(&result.driver); - ffStrbufInit(&result.apiVersion); - ffStrbufInit(&result.conformanceVersion); - ffListInit(&result.gpus, sizeof(FFGPUResult)); - - #ifdef FF_HAVE_VULKAN - result.error = detectVulkan(&result); - #else - result.error = "fastfetch was compiled without vulkan support"; - #endif + + if (result.gpus.elementSize == 0) + { + ffStrbufInit(&result.driver); + ffStrbufInit(&result.apiVersion); + ffStrbufInit(&result.conformanceVersion); + ffListInit(&result.gpus, sizeof(FFGPUResult)); + + #ifdef FF_HAVE_VULKAN + result.error = detectVulkan(&result); + #else + result.error = "fastfetch was compiled without vulkan support"; + #endif + } return &result; } From bb489f9af31397681bd82e0f3f4b0c677a098578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 30 Dec 2023 18:13:54 +0800 Subject: [PATCH 76/81] Common: get rid of `detection/internal.h` --- src/detection/cpu/cpu.c | 1 - src/detection/displayserver/displayserver.c | 14 ++++++++++--- .../displayserver/displayserver_android.c | 8 ++------ .../displayserver/displayserver_apple.c | 15 +++----------- .../displayserver/displayserver_windows.c | 20 ++++++++----------- .../displayserver/linux/displayserver_linux.c | 7 ------- src/detection/font/font.c | 1 - src/detection/gpu/gpu.c | 1 - src/detection/internal.h | 12 ----------- src/detection/media/media.c | 11 ++++++---- src/detection/os/os.c | 20 +++++++++++++++---- src/detection/os/os_android.c | 14 +++---------- src/detection/os/os_apple.m | 12 ----------- src/detection/os/os_linux.c | 11 ---------- src/detection/os/os_windows.cpp | 11 ---------- src/detection/packages/packages.c | 1 - src/detection/terminalfont/terminalfont.c | 1 - 17 files changed, 50 insertions(+), 110 deletions(-) delete mode 100644 src/detection/internal.h diff --git a/src/detection/cpu/cpu.c b/src/detection/cpu/cpu.c index b95a354ad4..5edc2f4340 100644 --- a/src/detection/cpu/cpu.c +++ b/src/detection/cpu/cpu.c @@ -1,5 +1,4 @@ #include "cpu.h" -#include "detection/internal.h" const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu); diff --git a/src/detection/displayserver/displayserver.c b/src/detection/displayserver/displayserver.c index 0b0db7833a..12e273dc5b 100644 --- a/src/detection/displayserver/displayserver.c +++ b/src/detection/displayserver/displayserver.c @@ -1,5 +1,4 @@ #include "displayserver.h" -#include "detection/internal.h" bool ffdsAppendDisplay( FFDisplayServerResult* result, @@ -36,7 +35,16 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds); const FFDisplayServerResult* ffConnectDisplayServer() { - FF_DETECTION_INTERNAL_GUARD(FFDisplayServerResult, + static FFDisplayServerResult result; + if (result.displays.elementSize == 0) + { + ffStrbufInit(&result.wmProcessName); + ffStrbufInit(&result.wmPrettyName); + ffStrbufInit(&result.wmProtocolName); + ffStrbufInit(&result.deProcessName); + ffStrbufInit(&result.dePrettyName); + ffListInit(&result.displays, sizeof(FFDisplayResult)); ffConnectDisplayServerImpl(&result); - ); + } + return &result; } diff --git a/src/detection/displayserver/displayserver_android.c b/src/detection/displayserver/displayserver_android.c index a1c7508ac6..8d3aa20a35 100644 --- a/src/detection/displayserver/displayserver_android.c +++ b/src/detection/displayserver/displayserver_android.c @@ -102,12 +102,8 @@ static bool detectWithGetprop(FFDisplayServerResult* ds) void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - ffStrbufInitStatic(&ds->wmProcessName, "WindowManager"); - ffStrbufInitStatic(&ds->wmPrettyName, "Window Manager"); - ffStrbufInit(&ds->wmProtocolName); - ffStrbufInit(&ds->deProcessName); - ffStrbufInit(&ds->dePrettyName); - ffListInitA(&ds->displays, sizeof(FFDisplayResult), 0); + ffStrbufSetStatic(&ds->wmProcessName, "WindowManager"); + ffStrbufSetStatic(&ds->wmPrettyName, "Window Manager"); if (!detectWithGetprop(ds)) detectWithDumpsys(ds); diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 352feafb32..3a63fb3033 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -73,20 +73,11 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) FF_CFTYPE_AUTO_RELEASE CFMachPortRef port = CGWindowServerCreateServerPort(); if (port) { - ffStrbufInitStatic(&ds->wmProcessName, "WindowServer"); - ffStrbufInitStatic(&ds->wmPrettyName, "Quartz Compositor"); - } - else - { - ffStrbufInit(&ds->wmProcessName); - ffStrbufInit(&ds->wmPrettyName); + ffStrbufSetStatic(&ds->wmProcessName, "WindowServer"); + ffStrbufSetStatic(&ds->wmPrettyName, "Quartz Compositor"); } } - ffStrbufInit(&ds->wmProtocolName); - - ffStrbufInit(&ds->deProcessName); - ffStrbufInitStatic(&ds->dePrettyName, "Aqua"); + ffStrbufSetStatic(&ds->dePrettyName, "Aqua"); - ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4); detectDisplays(ds); } diff --git a/src/detection/displayserver/displayserver_windows.c b/src/detection/displayserver/displayserver_windows.c index 5573d36016..684f299287 100644 --- a/src/detection/displayserver/displayserver_windows.c +++ b/src/detection/displayserver/displayserver_windows.c @@ -13,10 +13,10 @@ typedef struct FFMonitorInfo } FFMonitorInfo; static CALLBACK BOOL MonitorEnumProc( - HMONITOR hMonitor, - FF_MAYBE_UNUSED HDC hdc, - FF_MAYBE_UNUSED LPRECT lpRect, - LPARAM lParam + HMONITOR hMonitor, + FF_MAYBE_UNUSED HDC hdc, + FF_MAYBE_UNUSED LPRECT lpRect, + LPARAM lParam ) { FFlist* monitors = (FFlist*) lParam; @@ -145,20 +145,16 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) BOOL enabled; if(SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) { - ffStrbufInitStatic(&ds->wmProcessName, "dwm.exe"); - ffStrbufInitStatic(&ds->wmPrettyName, "Desktop Window Manager"); + ffStrbufSetStatic(&ds->wmProcessName, "dwm.exe"); + ffStrbufSetStatic(&ds->wmPrettyName, "Desktop Window Manager"); } else { // `explorer.exe` only provides a subset of WM functions, as well as the taskbar and desktop icons. // While a window itself is drawn by kernel (GDI). Killing `explorer.exe` won't affect how windows are displayed generally. - ffStrbufInitStatic(&ds->wmProcessName, "explorer.exe"); - ffStrbufInitStatic(&ds->wmPrettyName, "Internal"); + ffStrbufSetStatic(&ds->wmProcessName, "explorer.exe"); + ffStrbufSetStatic(&ds->wmPrettyName, "Internal"); } - ffStrbufInit(&ds->wmProtocolName); - ffStrbufInit(&ds->deProcessName); - ffStrbufInit(&ds->dePrettyName); - ffListInit(&ds->displays, sizeof(FFDisplayResult)); detectDisplays(ds); diff --git a/src/detection/displayserver/linux/displayserver_linux.c b/src/detection/displayserver/linux/displayserver_linux.c index e75e311b00..60168b0dc9 100644 --- a/src/detection/displayserver/linux/displayserver_linux.c +++ b/src/detection/displayserver/linux/displayserver_linux.c @@ -3,13 +3,6 @@ void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) { - ffStrbufInit(&ds->wmProcessName); - ffStrbufInit(&ds->wmPrettyName); - ffStrbufInit(&ds->wmProtocolName); - ffStrbufInit(&ds->deProcessName); - ffStrbufInit(&ds->dePrettyName); - ffListInitA(&ds->displays, sizeof(FFDisplayResult), 4); - if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) { //We try wayland as our preferred display server, as it supports the most features. diff --git a/src/detection/font/font.c b/src/detection/font/font.c index 6de21cfdfb..c0cced9a6e 100644 --- a/src/detection/font/font.c +++ b/src/detection/font/font.c @@ -1,5 +1,4 @@ #include "font.h" -#include "detection/internal.h" const char* ffDetectFontImpl(FFFontResult* font); diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 3fd82ca6b9..435d687aa7 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -1,5 +1,4 @@ #include "gpu.h" -#include "detection/internal.h" #include "detection/vulkan/vulkan.h" #include "detection/opengl/opengl.h" diff --git a/src/detection/internal.h b/src/detection/internal.h deleted file mode 100644 index ef691f7341..0000000000 --- a/src/detection/internal.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "common/thread.h" - -#define FF_DETECTION_INTERNAL_GUARD(ResultType, ...) \ - static ResultType result; \ - static bool init = false; \ - if(init) \ - return &result; \ - init = true; \ - __VA_ARGS__; \ - return &result; diff --git a/src/detection/media/media.c b/src/detection/media/media.c index 50604342bd..c24d8a1c42 100644 --- a/src/detection/media/media.c +++ b/src/detection/media/media.c @@ -1,11 +1,13 @@ #include "media.h" -#include "detection/internal.h" void ffDetectMediaImpl(FFMediaResult* media); const FFMediaResult* ffDetectMedia(void) { - FF_DETECTION_INTERNAL_GUARD(FFMediaResult, + static FFMediaResult result; + + if (result.error.chars == NULL) + { ffStrbufInit(&result.error); ffStrbufInit(&result.playerId); ffStrbufInit(&result.player); @@ -14,10 +16,11 @@ const FFMediaResult* ffDetectMedia(void) ffStrbufInit(&result.album); ffStrbufInit(&result.url); ffStrbufInit(&result.status); - ffDetectMediaImpl(&result); if(result.song.length == 0 && result.error.length == 0) ffStrbufAppendS(&result.error, "No media found"); - ); + } + + return &result; } diff --git a/src/detection/os/os.c b/src/detection/os/os.c index c09935954e..c8f10d5f13 100644 --- a/src/detection/os/os.c +++ b/src/detection/os/os.c @@ -1,11 +1,23 @@ #include "os.h" -#include "detection/internal.h" void ffDetectOSImpl(FFOSResult* os); const FFOSResult* ffDetectOS(void) { - FF_DETECTION_INTERNAL_GUARD(FFOSResult, - ffDetectOSImpl(&result) - ); + static FFOSResult result; + if (result.name.chars == NULL) + { + ffStrbufInit(&result.name); + ffStrbufInit(&result.prettyName); + ffStrbufInit(&result.id); + ffStrbufInit(&result.version); + ffStrbufInit(&result.versionID); + ffStrbufInit(&result.codename); + ffStrbufInit(&result.buildID); + ffStrbufInit(&result.idLike); + ffStrbufInit(&result.variant); + ffStrbufInit(&result.variantID); + ffDetectOSImpl(&result); + } + return &result; } diff --git a/src/detection/os/os_android.c b/src/detection/os/os_android.c index 1877aadfba..17752a27b6 100644 --- a/src/detection/os/os_android.c +++ b/src/detection/os/os_android.c @@ -3,25 +3,17 @@ void ffDetectOSImpl(FFOSResult* os) { - ffStrbufInitStatic(&os->name, "Android"); + ffStrbufSetStatic(&os->name, "Android"); - ffStrbufInitStatic(&os->prettyName, "Android"); + ffStrbufSetStatic(&os->prettyName, "Android"); - ffStrbufInitStatic(&os->id, "android"); + ffStrbufSetStatic(&os->id, "android"); - ffStrbufInit(&os->version); ffSettingsGetAndroidProperty("ro.build.version.release", &os->version); - ffStrbufInit(&os->versionID); ffSettingsGetAndroidProperty("ro.build.version.release", &os->versionID); - ffStrbufInit(&os->codename); ffSettingsGetAndroidProperty("ro.build.version.codename", &os->codename); - ffStrbufInit(&os->buildID); ffSettingsGetAndroidProperty("ro.build.id", &os->buildID); - - ffStrbufInit(&os->idLike); - ffStrbufInit(&os->variant); - ffStrbufInit(&os->variantID); } diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index 1ce516e252..70687811e6 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -98,18 +98,6 @@ static void parseOSXSoftwareLicense(FFOSResult* os) void ffDetectOSImpl(FFOSResult* os) { - ffStrbufInit(&os->name); - ffStrbufInit(&os->version); - ffStrbufInit(&os->buildID); - ffStrbufInit(&os->id); - ffStrbufInit(&os->prettyName); - ffStrbufInit(&os->versionID); - - ffStrbufInit(&os->codename); - ffStrbufInit(&os->idLike); - ffStrbufInit(&os->variant); - ffStrbufInit(&os->variantID); - parseSystemVersion(os); if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS")) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 84a213edc3..5058033a27 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -167,17 +167,6 @@ static void detectOS(FFOSResult* os) void ffDetectOSImpl(FFOSResult* os) { - ffStrbufInit(&os->name); - ffStrbufInit(&os->prettyName); - ffStrbufInit(&os->id); - ffStrbufInit(&os->idLike); - ffStrbufInit(&os->variant); - ffStrbufInit(&os->variantID); - ffStrbufInit(&os->version); - ffStrbufInit(&os->versionID); - ffStrbufInit(&os->codename); - ffStrbufInit(&os->buildID); - detectOS(os); if(ffStrbufIgnCaseEqualS(&os->id, "ubuntu")) diff --git a/src/detection/os/os_windows.cpp b/src/detection/os/os_windows.cpp index 772f095000..bd442da7da 100644 --- a/src/detection/os/os_windows.cpp +++ b/src/detection/os/os_windows.cpp @@ -42,17 +42,6 @@ static const char* getOsNameByWinbrand(FFstrbuf* osName) extern "C" void ffDetectOSImpl(FFOSResult* os) { - ffStrbufInit(&os->name); - ffStrbufInit(&os->prettyName); - ffStrbufInit(&os->id); - ffStrbufInit(&os->idLike); - ffStrbufInit(&os->variant); - ffStrbufInit(&os->variantID); - ffStrbufInit(&os->version); - ffStrbufInit(&os->versionID); - ffStrbufInit(&os->codename); - ffStrbufInit(&os->buildID); - if(getOsNameByWinbrand(&os->variant) && getOsNameByWmi(&os->variant)) return; diff --git a/src/detection/packages/packages.c b/src/detection/packages/packages.c index 2d1268a807..b3549a16aa 100644 --- a/src/detection/packages/packages.c +++ b/src/detection/packages/packages.c @@ -1,5 +1,4 @@ #include "packages.h" -#include "detection/internal.h" #include diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index e6b5ea66e4..23932ef819 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -1,7 +1,6 @@ #include "terminalfont.h" #include "common/properties.h" #include "common/processing.h" -#include "detection/internal.h" #include "detection/terminalshell/terminalshell.h" static void detectAlacritty(FFTerminalFontResult* terminalFont) From cae4b1c657a44a9f1fa85813b5a82a064080f951 Mon Sep 17 00:00:00 2001 From: Souma <101255979+5ouma@users.noreply.github.com> Date: Sun, 31 Dec 2023 18:35:57 +0900 Subject: [PATCH 77/81] chore(terminalshell_linux.c): Ignore `cwterm` as well as `figterm` Since CodeWhisperer overrides the terminal environment. --- src/detection/terminalshell/terminalshell_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index bc7f4027f8..327ba9772c 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -181,7 +181,7 @@ static void getTerminalShell(FFTerminalShellResult* result, pid_t pid) #ifdef __APPLE__ // https://github.com/fastfetch-cli/fastfetch/discussions/501 - if (ffStrEndsWith(name, " (figterm)")) + if (ffStrEndsWith(name, " (figterm)") || ffStrEndsWith(name, " (cwterm)")) getProcessNameAndPpid(ppid, name, &ppid); #endif From 3f553b32663c103aa4672e70c263f27380c40225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 31 Dec 2023 18:43:44 +0800 Subject: [PATCH 78/81] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f52a3bdad1..e0032216b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Bugfixes: * Fix Windows partition detection for WSL2 (Linux, Disk) * Fix Btrfs subvolumes being detected as external partitions some times (Linux, Disk) * Fix battery cycle counts in some places (Battery) +* Fix CodeWhisperer compatibility (#676, Terminal, macOS) # 2.4.0 From a56c092a78deae131901f6594053d4e81db55dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 31 Dec 2023 18:44:32 +0800 Subject: [PATCH 79/81] Release: v2.5.0 Happy new year! --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0032216b4..3fa5191071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# 2.4.1 +# 2.5.0 Changes: * `--gpu-use-nvml` has been renamed to `--gpu-driver-specific` due to using of `IGCL` and `AGS` diff --git a/CMakeLists.txt b/CMakeLists.txt index ab3b72a22f..21f0051a87 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.4.0 + VERSION 2.5.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 553338b2bc562c2f73cb90e9d4f178944ceda6a6 Mon Sep 17 00:00:00 2001 From: AlbydS <119180144+AlbydST@users.noreply.github.com> Date: Sun, 31 Dec 2023 19:24:47 +0100 Subject: [PATCH 80/81] Add more Linux distributions to installation guide I added Alpine Linux, NixOS and openSUSE to the installation guide. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 168c17bf62..bc8323ebdb 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,11 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ * Arch Linux: `sudo pacman -S fastfetch` * Fedora: `sudo dnf install fastfetch` * Gentoo: `sudo emerge --ask app-misc/fastfetch` +* Alpine: `sudo pkg install fastfetch` +* NixOS: `sudo nix-shell -p fastfetch` +* openSUSE: `sudo zypper install fastfetch` + +Replace sudo with doas depending on what you use. [See also if fastfetch has been packaged for your favorite Linux distro](#Packaging) From a95a80aa93e9b8f26bc2514ccc4822340e47a438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 1 Jan 2024 10:50:04 +0800 Subject: [PATCH 81/81] README: remove invalid info --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index bc8323ebdb..41e5cddbf3 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,6 @@ There are [screenshots on different platforms](https://github.com/fastfetch-cli/ * Arch Linux: `sudo pacman -S fastfetch` * Fedora: `sudo dnf install fastfetch` * Gentoo: `sudo emerge --ask app-misc/fastfetch` -* Alpine: `sudo pkg install fastfetch` * NixOS: `sudo nix-shell -p fastfetch` * openSUSE: `sudo zypper install fastfetch`