blob: d0992628c782731e53a9f1d4b5a48a5a5b50c8eb [file]
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <arm/linux/api.h>
#include <log.h>
/*
* Map from Android GPU series ID to Android GPU vendor ID.
* This map is used to avoid storing vendor IDs in tables.
*/
static enum cpuinfo_android_gpu_vendor gpu_series_vendor[cpuinfo_android_gpu_series_max] = {
[cpuinfo_android_gpu_series_unknown] = cpuinfo_android_gpu_vendor_unknown,
[cpuinfo_android_gpu_series_arm_mali] = cpuinfo_android_gpu_vendor_arm,
[cpuinfo_android_gpu_series_arm_mali_t] = cpuinfo_android_gpu_vendor_arm,
[cpuinfo_android_gpu_series_arm_mali_g] = cpuinfo_android_gpu_vendor_arm,
[cpuinfo_android_gpu_series_broadcom_videocore] = cpuinfo_android_gpu_vendor_broadcom,
[cpuinfo_android_gpu_series_intel_gen] = cpuinfo_android_gpu_vendor_intel,
[cpuinfo_android_gpu_series_intel_hd_graphics] = cpuinfo_android_gpu_vendor_intel,
[cpuinfo_android_gpu_series_nvidia_tegra] = cpuinfo_android_gpu_vendor_nvidia,
[cpuinfo_android_gpu_series_nvidia_tegra_k] = cpuinfo_android_gpu_vendor_nvidia,
[cpuinfo_android_gpu_series_nvidia_tegra_x] = cpuinfo_android_gpu_vendor_nvidia,
[cpuinfo_android_gpu_series_powervr_sgx] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_powervr_rogue_g] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_powervr_rogue_ge] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_powervr_rogue_gm] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_powervr_rogue_gt] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_powervr_rogue_gx] = cpuinfo_android_gpu_vendor_powervr,
[cpuinfo_android_gpu_series_qualcomm_adreno] = cpuinfo_android_gpu_vendor_qualcomm,
[cpuinfo_android_gpu_series_vivante_gc] = cpuinfo_android_gpu_vendor_vivante,
};
/* Map from Android GPU vendor ID to its string representation */
static const char* gpu_vendor_string[cpuinfo_arm_chipset_vendor_max] = {
[cpuinfo_android_gpu_vendor_unknown] = "Unknown",
[cpuinfo_android_gpu_vendor_arm] = "ARM",
[cpuinfo_android_gpu_vendor_broadcom] = "Broadcom",
[cpuinfo_android_gpu_vendor_intel] = "Intel",
[cpuinfo_android_gpu_vendor_nvidia] = "Nvidia",
[cpuinfo_android_gpu_vendor_powervr] = "PowerVR",
[cpuinfo_android_gpu_vendor_qualcomm] = "Qualcomm",
[cpuinfo_android_gpu_vendor_vivante] = "Vivante",
};
/* Map from ARM chipset series ID to its string representation */
static const char* gpu_series_string[cpuinfo_arm_chipset_series_max] = {
[cpuinfo_android_gpu_series_arm_mali] = "Mali-",
[cpuinfo_android_gpu_series_arm_mali_t] = "Mali-T",
[cpuinfo_android_gpu_series_arm_mali_g] = "Mali-G",
[cpuinfo_android_gpu_series_broadcom_videocore] = "VideoCore ",
[cpuinfo_android_gpu_series_intel_gen] = "Gen ",
[cpuinfo_android_gpu_series_intel_hd_graphics] = "HD Graphics ",
[cpuinfo_android_gpu_series_nvidia_tegra] = "Tegra ",
[cpuinfo_android_gpu_series_nvidia_tegra_k] = "Tegra K",
[cpuinfo_android_gpu_series_nvidia_tegra_x] = "Tegra X",
[cpuinfo_android_gpu_series_powervr_sgx] = "SGX",
[cpuinfo_android_gpu_series_powervr_rogue_g] = "Rogue G",
[cpuinfo_android_gpu_series_powervr_rogue_ge] = "Rogue GE",
[cpuinfo_android_gpu_series_powervr_rogue_gm] = "Rogue GM",
[cpuinfo_android_gpu_series_powervr_rogue_gt] = "Rogue GT",
[cpuinfo_android_gpu_series_powervr_rogue_gx] = "Rogue GX",
[cpuinfo_android_gpu_series_qualcomm_adreno] = "Adreno ",
[cpuinfo_android_gpu_series_vivante_gc] = "GC",
};
/* Convert GPU name represented by cpuinfo_android_gpu structure to a string representation */
void cpuinfo_android_gpu_to_string(
const struct cpuinfo_android_gpu gpu[restrict static 1],
char name[restrict static CPUINFO_GPU_NAME_MAX])
{
enum cpuinfo_android_gpu_vendor vendor = gpu->vendor;
if (vendor >= cpuinfo_android_gpu_vendor_max) {
vendor = cpuinfo_android_gpu_vendor_unknown;
}
enum cpuinfo_android_gpu_series series = gpu->series;
if (series >= cpuinfo_android_gpu_series_max) {
series = cpuinfo_android_gpu_series_unknown;
}
const char* vendor_string = gpu_vendor_string[vendor];
const char* series_string = gpu_series_string[series];
const uint32_t model = gpu->model;
if (model == 0) {
if (series == cpuinfo_android_gpu_series_unknown) {
strncpy(name, vendor_string, CPUINFO_GPU_NAME_MAX);
} else {
snprintf(name, CPUINFO_GPU_NAME_MAX,
"%s %s", vendor_string, series_string);
}
} else {
snprintf(name, CPUINFO_GPU_NAME_MAX,
"%s %s%"PRIu32"%.*s",
vendor_string, series_string, model,
(int) strnlen(gpu->suffix, CPUINFO_ANDROID_GPU_SUFFIX_MAX), gpu->suffix);
}
}
/*
* Decodes GPU name from OpenGL (ES) GL_RENDERER string.
*
* @param[in] renderer - the GL_RENDERER string.
*
* @returns Decoded GPU name. If GPU could not be decoded, the resulting structure would use `unknown` vendor
* and series identifiers.
*/
struct cpuinfo_android_gpu cpuinfo_android_decode_gpu(const char* renderer) {
struct cpuinfo_android_gpu gpu;
memset(&gpu, 0, sizeof(gpu));
if (renderer != NULL) {
switch (renderer[0]) {
case 'A':
if (sscanf(renderer, "Adreno (TM) %"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_qualcomm_adreno;
}
break;
case 'G':
if (sscanf(renderer, "GC%"SCNu32" core", &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_vivante_gc;
}
break;
case 'I':
if (strcmp(renderer, "Immersion.16") == 0) {
/* Vivante GC4000 in early HiSilicon chipsets */
gpu.series = cpuinfo_android_gpu_series_vivante_gc;
gpu.model = 4000;
} else if (strcmp(renderer, "Intel(R) HD Graphics for BayTrail") == 0) {
gpu.series = cpuinfo_android_gpu_series_intel_gen;
gpu.model = 7;
} else if (strcmp(renderer, "Intel(R) HD Graphics for Atom(TM) x5/x7") == 0) {
gpu.series = cpuinfo_android_gpu_series_intel_gen;
gpu.model = 8;
}
break;
case 'M':
if (sscanf(renderer, "Mali-%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_arm_mali;
} else if (sscanf(renderer, "Mali-T%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_arm_mali_t;
} else if (sscanf(renderer, "Mali-G%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_arm_mali_g;
} else if (sscanf(renderer, "Mesa DRI Intel(R) HD Graphics %"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_intel_hd_graphics;
} else if (strcmp(renderer, "Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2") == 0) {
gpu.series = cpuinfo_android_gpu_series_intel_gen;
gpu.model = 6;
}
break;
case 'N':
if (strcmp(renderer, "NVIDIA Tegra 3") == 0) {
gpu.series = cpuinfo_android_gpu_series_nvidia_tegra;
gpu.model = 3;
} else if (strcmp(renderer, "NVIDIA Tegra") == 0) {
gpu.series = cpuinfo_android_gpu_series_nvidia_tegra;
gpu.model = 0;
}
break;
case 'P':
if (strcmp(renderer, "PXA1928 GPU") == 0) {
/* Vivante GC5000 in PXA1928 chipset */
gpu.series = cpuinfo_android_gpu_series_vivante_gc;
gpu.model = 5000;
} else if (sscanf(renderer, "PowerVR SGX %"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_sgx;
} else if (sscanf(renderer, "PowerVR Rogue G%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_g;
} else if (sscanf(renderer, "PowerVR Rogue GE%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_ge;
} else if (sscanf(renderer, "PowerVR Rogue GM%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_gm;
} else if (sscanf(renderer, "PowerVR Rogue GT%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_gt;
} else if (sscanf(renderer, "PowerVR Rogue GX%"SCNu32, &gpu.model) == 1 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_gx;
} else if (strcmp(renderer, "PowerVR Rogue Han") == 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_g;
gpu.model = 6200;
} else if (strcmp(renderer, "PowerVR Rogue Hood") == 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_g;
gpu.model = 6430;
} else if (strcmp(renderer, "PowerVR Rogue Marlowe") == 0) {
gpu.series = cpuinfo_android_gpu_series_powervr_rogue_gt;
gpu.model = 7400;
gpu.suffix[0] = '+';
}
break;
case 'S':
if (strcmp(renderer, "Sapphire 650") == 0) {
/* ARM Mali-T720 in some MT8163 chipsets */
gpu.series = cpuinfo_android_gpu_series_arm_mali_t;
gpu.model = 720;
}
break;
case 'V':
if (strcmp(renderer, "VideoCore IV HW") == 0) {
gpu.series = cpuinfo_android_gpu_series_broadcom_videocore;
gpu.model = 4;
} else if (sscanf(renderer, "Vivante GC%"SCNu32"%3s", &gpu.model, gpu.suffix) == 2 && gpu.model != 0) {
gpu.series = cpuinfo_android_gpu_series_vivante_gc;
}
break;
}
}
gpu.vendor = gpu_series_vendor[gpu.series];
return gpu;
}