CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/UI/DriverManagerScreen.cpp
Views: 1401
#include "Common/File/VFS/ZipFileReader.h"1#include "Common/Data/Format/JSONReader.h"2#include "Common/System/OSD.h"3#include "Common/Log.h"4#include "Common/StringUtils.h"56#include "Core/Config.h"7#include "Core/System.h"89#include "UI/View.h"10#include "UI/DriverManagerScreen.h"11#include "UI/GameSettingsScreen.h" // for triggerrestart12#include "UI/OnScreenDisplay.h"1314static Path GetDriverPath() {15if (g_Config.internalDataDirectory.empty()) {16Path curDir = File::GetCurDirectory();17// This is the case when testing on PC18return GetSysDirectory(DIRECTORY_PSP) / "drivers";19} else {20// On Android, this is set to something usable.21return g_Config.internalDataDirectory / "drivers";22}23}2425// Example meta.json:26// {27// "schemaVersion": 1,28// "name" : "Turnip driver revision 14",29// "description" : "Compiled from Mesa source.",30// "author" : "KIMCHI",31// "packageVersion" : "1",32// "vendor" : "Mesa",33// "driverVersion" : "Vulkan 1.3.274",34// "minApi" : 27,35// "libraryName" : "vulkan.ad07XX.so"36// }3738struct DriverMeta {39int minApi;40std::string name;41std::string description;42std::string vendor;43std::string driverVersion;4445bool Read(std::string_view str, std::string *errorStr) {46// Validate the json file. TODO: Be a bit more detailed.47json::JsonReader meta = json::JsonReader((const char *)str.data(), str.size());48if (!meta.ok()) {49*errorStr = "meta.json not valid json";50return false;51}5253int schemaVersion = meta.root().getInt("schemaVersion");54if (schemaVersion > 1) {55*errorStr = "unknown schemaVersion in meta.json";56return false;57}5859if (!meta.root().getString("name", &name) || name.empty()) {60*errorStr = "missing driver name in json";61return false;62}63meta.root().getString("description", &description);64meta.root().getString("vendor", &vendor);65meta.root().getString("driverVersion", &driverVersion);66minApi = meta.root().getInt("minApi");67return true;68}69};7071// Compound view, creating a FileChooserChoice inside.72class DriverChoice : public UI::LinearLayout {73public:74DriverChoice(const std::string &driverName, bool current, UI::LayoutParams *layoutParams = nullptr);7576UI::Event OnUse;77UI::Event OnDelete;78std::string name_;79};8081static constexpr UI::Size ITEM_HEIGHT = 64.f;8283DriverChoice::DriverChoice(const std::string &driverName, bool current, UI::LayoutParams *layoutParams) : UI::LinearLayout(UI::ORIENT_VERTICAL, layoutParams), name_(driverName) {84using namespace UI;85SetSpacing(2.0f);86if (!layoutParams) {87layoutParams_->width = FILL_PARENT;88layoutParams_->height = 220;89}90auto gr = GetI18NCategory(I18NCat::GRAPHICS);91auto di = GetI18NCategory(I18NCat::DIALOG);9293// Read the meta data94DriverMeta meta{};95bool isDefault = driverName.empty();96if (isDefault) {97meta.description = gr->T("Default GPU driver");98}99100Path metaPath = GetDriverPath() / driverName / "meta.json";101std::string metaJson;102if (File::ReadTextFileToString(metaPath, &metaJson)) {103std::string errorStr;104meta.Read(metaJson, &errorStr);105}106Add(new Spacer(12.0));107108#if PPSSPP_PLATFORM(ANDROID)109bool usable = isDefault || meta.minApi <= System_GetPropertyInt(SYSPROP_SYSTEMVERSION);110#else111// For testing only112bool usable = isDefault || true;113#endif114115Add(new ItemHeader(driverName.empty() ? gr->T("Default GPU driver") : driverName))->SetLarge(true);116if (current) {117Add(new NoticeView(NoticeLevel::SUCCESS, gr->T("Current GPU driver"), ""));118}119120auto horizBar = Add(new UI::LinearLayout(UI::ORIENT_HORIZONTAL));121std::string desc = meta.description;122if (!desc.empty()) desc += "\n";123if (!isDefault)124desc += meta.vendor + ": " + meta.driverVersion;125horizBar->Add(new TextView(desc));126if (!current && !isDefault) {127horizBar->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(ITEM_HEIGHT, ITEM_HEIGHT)))->OnClick.Add([=](UI::EventParams &) {128UI::EventParams e{};129e.s = name_;130OnDelete.Trigger(e);131return UI::EVENT_DONE;132});133}134if (usable) {135if (!current) {136Add(new Choice(di->T("Select")))->OnClick.Add([=](UI::EventParams &) {137UI::EventParams e{};138e.s = name_;139OnUse.Trigger(e);140return UI::EVENT_DONE;141});142}143} else {144Add(new NoticeView(NoticeLevel::WARN, ApplySafeSubstitutions(gr->T("Driver requires Android API version %1, current is %2"), meta.minApi, System_GetPropertyInt(SYSPROP_SYSTEMVERSION)),""));145}146}147148DriverManagerScreen::DriverManagerScreen(const Path & gamePath) : TabbedUIDialogScreenWithGameBackground(gamePath) {}149150void DriverManagerScreen::CreateTabs() {151using namespace UI;152auto gr = GetI18NCategory(I18NCat::GRAPHICS);153154LinearLayout *drivers = AddTab("DriverManagerDrivers", gr->T("Drivers"));155CreateDriverTab(drivers);156}157158void DriverManagerScreen::CreateDriverTab(UI::ViewGroup *drivers) {159using namespace UI;160auto di = GetI18NCategory(I18NCat::DIALOG);161auto gr = GetI18NCategory(I18NCat::GRAPHICS);162163drivers->Add(new ItemHeader(gr->T("AdrenoTools driver manager")));164auto customDriverInstallChoice = drivers->Add(new Choice(gr->T("Install custom driver...")));165drivers->Add(new Choice(di->T("More information...")))->OnClick.Add([=](UI::EventParams &e) {166System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/docs/reference/custom-drivers/");167return UI::EVENT_DONE;168});169170customDriverInstallChoice->OnClick.Handle(this, &DriverManagerScreen::OnCustomDriverInstall);171172drivers->Add(new ItemHeader(gr->T("Drivers")));173bool isDefault = g_Config.sCustomDriver.empty();174drivers->Add(new DriverChoice("", isDefault))->OnUse.Handle(this, &DriverManagerScreen::OnCustomDriverChange);175176const Path driverPath = GetDriverPath();177std::vector<File::FileInfo> listing;178if (File::GetFilesInDir(driverPath, &listing)) {179for (auto driver : listing) {180auto choice = drivers->Add(new DriverChoice(driver.name, g_Config.sCustomDriver == driver.name));181choice->OnUse.Handle(this, &DriverManagerScreen::OnCustomDriverChange);182choice->OnDelete.Handle(this, &DriverManagerScreen::OnCustomDriverUninstall);183}184}185drivers->Add(new Spacer(12.0));186}187188UI::EventReturn DriverManagerScreen::OnCustomDriverChange(UI::EventParams &e) {189auto di = GetI18NCategory(I18NCat::DIALOG);190191screenManager()->push(new PromptScreen(gamePath_, di->T("Changing this setting requires PPSSPP to restart."), di->T("Restart"), di->T("Cancel"), [=](bool yes) {192if (yes) {193INFO_LOG(Log::G3D, "Switching driver to '%s'", e.s.c_str());194g_Config.sCustomDriver = e.s;195TriggerRestart("GameSettingsScreen::CustomDriverYes", false, gamePath_);196}197}));198return UI::EVENT_DONE;199}200201UI::EventReturn DriverManagerScreen::OnCustomDriverUninstall(UI::EventParams &e) {202if (e.s.empty()) {203return UI::EVENT_DONE;204}205INFO_LOG(Log::G3D, "Uninstalling driver: %s", e.s.c_str());206207Path folder = GetDriverPath() / e.s;208File::DeleteDirRecursively(folder);209210RecreateViews();211return UI::EVENT_DONE;212}213214UI::EventReturn DriverManagerScreen::OnCustomDriverInstall(UI::EventParams &e) {215auto gr = GetI18NCategory(I18NCat::GRAPHICS);216217System_BrowseForFile(GetRequesterToken(), gr->T("Install custom driver..."), BrowseFileType::ZIP, [this](const std::string &value, int) {218if (value.empty()) {219return;220}221222auto gr = GetI18NCategory(I18NCat::GRAPHICS);223224Path zipPath = Path(value);225226// Don't bother checking the file extension. Can't always do that with files from Download (they have paths like content://com.android.providers.downloads.documents/document/msf%3A1000001095).227// Though, it may be possible to get it in other ways.228229std::unique_ptr<ZipFileReader> zipFileReader = std::unique_ptr<ZipFileReader>(ZipFileReader::Create(zipPath, "", true));230if (!zipFileReader) {231g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver", "couldn't open zip"));232ERROR_LOG(Log::System, "Failed to open file '%s' as zip", zipPath.c_str());233return;234}235236size_t metaDataSize;237uint8_t *metaData = zipFileReader->ReadFile("meta.json", &metaDataSize);238if (!metaData) {239g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), "meta.json missing");240return;241}242243DriverMeta meta;244std::string errorStr;245if (!meta.Read(std::string_view((const char *)metaData, metaDataSize), &errorStr)) {246delete[] metaData;247g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), errorStr);248return;249}250delete[] metaData;251252const Path newCustomDriver = GetDriverPath() / meta.name;253NOTICE_LOG(Log::G3D, "Installing driver into '%s'", newCustomDriver.c_str());254File::CreateFullPath(newCustomDriver);255256std::vector<File::FileInfo> zipListing;257zipFileReader->GetFileListing("", &zipListing, nullptr);258259for (auto file : zipListing) {260File::CreateEmptyFile(newCustomDriver / file.name);261262size_t size;263uint8_t *data = zipFileReader->ReadFile(file.name.c_str(), &size);264if (!data) {265g_OSD.Show(OSDType::MESSAGE_ERROR, gr->T("The chosen ZIP file doesn't contain a valid driver"), file.name.c_str());266return;267}268File::WriteDataToFile(false, data, size, newCustomDriver / file.name);269delete[] data;270}271272auto iz = GetI18NCategory(I18NCat::INSTALLZIP);273g_OSD.Show(OSDType::MESSAGE_SUCCESS, iz->T("Installed!"));274RecreateViews();275});276return UI::EVENT_DONE;277}278279280