|
@@ -0,0 +1,145 @@
|
|
|
|
|
+package org.yuzu.yuzu_emu.utils
|
|
|
|
|
+
|
|
|
|
|
+import android.content.Context
|
|
|
|
|
+import android.net.Uri
|
|
|
|
|
+import org.yuzu.yuzu_emu.NativeLibrary
|
|
|
|
|
+import org.yuzu.yuzu_emu.utils.FileUtil.copyUriToInternalStorage
|
|
|
|
|
+import java.io.File
|
|
|
|
|
+import java.io.FileInputStream
|
|
|
|
|
+import java.io.FileOutputStream
|
|
|
|
|
+import java.io.IOException
|
|
|
|
|
+import java.util.zip.ZipInputStream
|
|
|
|
|
+
|
|
|
|
|
+object GpuDriverHelper {
|
|
|
|
|
+ private const val META_JSON_FILENAME = "meta.json"
|
|
|
|
|
+ private const val DRIVER_INTERNAL_FILENAME = "gpu_driver.zip"
|
|
|
|
|
+ private var fileRedirectionPath: String? = null
|
|
|
|
|
+ private var driverInstallationPath: String? = null
|
|
|
|
|
+ private var hookLibPath: String? = null
|
|
|
|
|
+
|
|
|
|
|
+ @Throws(IOException::class)
|
|
|
|
|
+ private fun unzip(zipFilePath: String, destDir: String) {
|
|
|
|
|
+ val dir = File(destDir)
|
|
|
|
|
+
|
|
|
|
|
+ // Create output directory if it doesn't exist
|
|
|
|
|
+ if (!dir.exists()) dir.mkdirs()
|
|
|
|
|
+
|
|
|
|
|
+ // Unpack the files.
|
|
|
|
|
+ val zis = ZipInputStream(FileInputStream(zipFilePath))
|
|
|
|
|
+ val buffer = ByteArray(1024)
|
|
|
|
|
+ var ze = zis.nextEntry
|
|
|
|
|
+ while (ze != null) {
|
|
|
|
|
+ val fileName = ze.name
|
|
|
|
|
+ val newFile = File(destDir + fileName)
|
|
|
|
|
+ newFile.parentFile!!.mkdirs()
|
|
|
|
|
+ val fos = FileOutputStream(newFile)
|
|
|
|
|
+ var len: Int
|
|
|
|
|
+ while (zis.read(buffer).also { len = it } > 0) {
|
|
|
|
|
+ fos.write(buffer, 0, len)
|
|
|
|
|
+ }
|
|
|
|
|
+ fos.close()
|
|
|
|
|
+ zis.closeEntry()
|
|
|
|
|
+ ze = zis.nextEntry
|
|
|
|
|
+ }
|
|
|
|
|
+ zis.closeEntry()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @JvmStatic
|
|
|
|
|
+ fun initializeDriverParameters(context: Context) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Initialize the file redirection directory.
|
|
|
|
|
+ fileRedirectionPath =
|
|
|
|
|
+ context.getExternalFilesDir(null)!!.canonicalPath + "/gpu/vk_file_redirect/"
|
|
|
|
|
+
|
|
|
|
|
+ // Initialize the driver installation directory.
|
|
|
|
|
+ driverInstallationPath = context.filesDir.canonicalPath + "/gpu_driver/"
|
|
|
|
|
+ } catch (e: IOException) {
|
|
|
|
|
+ throw RuntimeException(e)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Initialize directories.
|
|
|
|
|
+ initializeDirectories()
|
|
|
|
|
+
|
|
|
|
|
+ // Initialize hook libraries directory.
|
|
|
|
|
+ hookLibPath = context.applicationInfo.nativeLibraryDir + "/"
|
|
|
|
|
+
|
|
|
|
|
+ // Initialize GPU driver.
|
|
|
|
|
+ NativeLibrary.InitializeGpuDriver(
|
|
|
|
|
+ hookLibPath,
|
|
|
|
|
+ driverInstallationPath,
|
|
|
|
|
+ customDriverLibraryName,
|
|
|
|
|
+ fileRedirectionPath
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun installDefaultDriver(context: Context) {
|
|
|
|
|
+ // Removing the installed driver will result in the backend using the default system driver.
|
|
|
|
|
+ val driverInstallationDir = File(driverInstallationPath!!)
|
|
|
|
|
+ deleteRecursive(driverInstallationDir)
|
|
|
|
|
+ initializeDriverParameters(context)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun installCustomDriver(context: Context, driverPathUri: Uri?) {
|
|
|
|
|
+ // Revert to system default in the event the specified driver is bad.
|
|
|
|
|
+ installDefaultDriver(context)
|
|
|
|
|
+
|
|
|
|
|
+ // Ensure we have directories.
|
|
|
|
|
+ initializeDirectories()
|
|
|
|
|
+
|
|
|
|
|
+ // Copy the zip file URI into our private storage.
|
|
|
|
|
+ copyUriToInternalStorage(
|
|
|
|
|
+ context,
|
|
|
|
|
+ driverPathUri,
|
|
|
|
|
+ driverInstallationPath!!,
|
|
|
|
|
+ DRIVER_INTERNAL_FILENAME
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ // Unzip the driver.
|
|
|
|
|
+ try {
|
|
|
|
|
+ unzip(driverInstallationPath + DRIVER_INTERNAL_FILENAME, driverInstallationPath!!)
|
|
|
|
|
+ } catch (e: IOException) {
|
|
|
|
|
+ throw RuntimeException(e)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Initialize the driver parameters.
|
|
|
|
|
+ initializeDriverParameters(context)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Parse the custom driver metadata to retrieve the name.
|
|
|
|
|
+ val customDriverName: String?
|
|
|
|
|
+ get() {
|
|
|
|
|
+ // Parse the custom driver metadata to retrieve the name.
|
|
|
|
|
+ val metadata = GpuDriverMetadata(driverInstallationPath + META_JSON_FILENAME)
|
|
|
|
|
+ return metadata.name
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Parse the custom driver metadata to retrieve the library name.
|
|
|
|
|
+ private val customDriverLibraryName: String?
|
|
|
|
|
+ get() {
|
|
|
|
|
+ // Parse the custom driver metadata to retrieve the library name.
|
|
|
|
|
+ val metadata = GpuDriverMetadata(driverInstallationPath + META_JSON_FILENAME)
|
|
|
|
|
+ return metadata.libraryName
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private fun initializeDirectories() {
|
|
|
|
|
+ // Ensure the file redirection directory exists.
|
|
|
|
|
+ val fileRedirectionDir = File(fileRedirectionPath!!)
|
|
|
|
|
+ if (!fileRedirectionDir.exists()) {
|
|
|
|
|
+ fileRedirectionDir.mkdirs()
|
|
|
|
|
+ }
|
|
|
|
|
+ // Ensure the driver installation directory exists.
|
|
|
|
|
+ val driverInstallationDir = File(driverInstallationPath!!)
|
|
|
|
|
+ if (!driverInstallationDir.exists()) {
|
|
|
|
|
+ driverInstallationDir.mkdirs()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private fun deleteRecursive(fileOrDirectory: File) {
|
|
|
|
|
+ if (fileOrDirectory.isDirectory) {
|
|
|
|
|
+ for (child in fileOrDirectory.listFiles()!!) {
|
|
|
|
|
+ deleteRecursive(child)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ fileOrDirectory.delete()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|