Compare commits
1 Commits
android-42
...
android-37
Author | SHA1 | Date | |
---|---|---|---|
0f6f7fd552 |
@ -49,7 +49,6 @@ class LicenseAdapter(private val activity: AppCompatActivity, var licenses: List
|
|||||||
val context = YuzuApplication.appContext
|
val context = YuzuApplication.appContext
|
||||||
binding.textSettingName.text = context.getString(license.titleId)
|
binding.textSettingName.text = context.getString(license.titleId)
|
||||||
binding.textSettingDescription.text = context.getString(license.descriptionId)
|
binding.textSettingDescription.text = context.getString(license.descriptionId)
|
||||||
binding.textSettingValue.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,19 +5,13 @@ package org.yuzu.yuzu_emu.adapters
|
|||||||
|
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import org.yuzu.yuzu_emu.databinding.PageSetupBinding
|
import org.yuzu.yuzu_emu.databinding.PageSetupBinding
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
|
||||||
import org.yuzu.yuzu_emu.model.SetupCallback
|
|
||||||
import org.yuzu.yuzu_emu.model.SetupPage
|
import org.yuzu.yuzu_emu.model.SetupPage
|
||||||
import org.yuzu.yuzu_emu.model.StepState
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
|
||||||
|
|
||||||
class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :
|
class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>) :
|
||||||
RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() {
|
RecyclerView.Adapter<SetupAdapter.SetupPageViewHolder>() {
|
||||||
@ -32,7 +26,7 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
holder.bind(pages[position])
|
holder.bind(pages[position])
|
||||||
|
|
||||||
inner class SetupPageViewHolder(val binding: PageSetupBinding) :
|
inner class SetupPageViewHolder(val binding: PageSetupBinding) :
|
||||||
RecyclerView.ViewHolder(binding.root), SetupCallback {
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
lateinit var page: SetupPage
|
lateinit var page: SetupPage
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -41,12 +35,6 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
|
|
||||||
fun bind(page: SetupPage) {
|
fun bind(page: SetupPage) {
|
||||||
this.page = page
|
this.page = page
|
||||||
|
|
||||||
if (page.stepCompleted.invoke() == StepState.COMPLETE) {
|
|
||||||
binding.buttonAction.visibility = View.INVISIBLE
|
|
||||||
binding.textConfirmation.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.icon.setImageDrawable(
|
binding.icon.setImageDrawable(
|
||||||
ResourcesCompat.getDrawable(
|
ResourcesCompat.getDrawable(
|
||||||
activity.resources,
|
activity.resources,
|
||||||
@ -74,15 +62,9 @@ class SetupAdapter(val activity: AppCompatActivity, val pages: List<SetupPage>)
|
|||||||
MaterialButton.ICON_GRAVITY_END
|
MaterialButton.ICON_GRAVITY_END
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
page.buttonAction.invoke(this@SetupPageViewHolder)
|
page.buttonAction.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStepCompleted() {
|
|
||||||
ViewUtils.hideView(binding.buttonAction, 200)
|
|
||||||
ViewUtils.showView(binding.textConfirmation, 200)
|
|
||||||
ViewModelProvider(activity)[HomeViewModel::class.java].setShouldPageForward(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +207,8 @@ class SettingsAdapter(
|
|||||||
val sliderBinding = DialogSliderBinding.inflate(inflater)
|
val sliderBinding = DialogSliderBinding.inflate(inflater)
|
||||||
|
|
||||||
textSliderValue = sliderBinding.textValue
|
textSliderValue = sliderBinding.textValue
|
||||||
textSliderValue!!.text = String.format(
|
textSliderValue!!.text = sliderProgress.toString()
|
||||||
context.getString(R.string.value_with_units),
|
sliderBinding.textUnits.text = item.units
|
||||||
sliderProgress.toString(),
|
|
||||||
item.units
|
|
||||||
)
|
|
||||||
|
|
||||||
sliderBinding.slider.apply {
|
sliderBinding.slider.apply {
|
||||||
valueFrom = item.min.toFloat()
|
valueFrom = item.min.toFloat()
|
||||||
@ -219,11 +216,7 @@ class SettingsAdapter(
|
|||||||
value = sliderProgress.toFloat()
|
value = sliderProgress.toFloat()
|
||||||
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
addOnChangeListener { _: Slider, value: Float, _: Boolean ->
|
||||||
sliderProgress = value.toInt()
|
sliderProgress = value.toInt()
|
||||||
textSliderValue!!.text = String.format(
|
textSliderValue!!.text = sliderProgress.toString()
|
||||||
context.getString(R.string.value_with_units),
|
|
||||||
sliderProgress.toString(),
|
|
||||||
item.units
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +225,10 @@ class SettingsAdapter(
|
|||||||
.setView(sliderBinding.root)
|
.setView(sliderBinding.root)
|
||||||
.setPositiveButton(android.R.string.ok, this)
|
.setPositiveButton(android.R.string.ok, this)
|
||||||
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
|
.setNegativeButton(android.R.string.cancel, defaultCancelListener)
|
||||||
|
.setNeutralButton(R.string.slider_default) { dialog: DialogInterface, which: Int ->
|
||||||
|
sliderBinding.slider.value = item.defaultValue!!.toFloat()
|
||||||
|
onClick(dialog, which)
|
||||||
|
}
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,17 +25,12 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
|||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
binding.textSettingDescription.visibility = View.VISIBLE
|
binding.textSettingDescription.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
val epochTime = setting.value.toLong()
|
||||||
|
val instant = Instant.ofEpochMilli(epochTime * 1000)
|
||||||
|
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
|
||||||
|
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||||
|
binding.textSettingDescription.text = dateFormatter.format(zonedTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
|
||||||
val epochTime = setting.value.toLong()
|
|
||||||
val instant = Instant.ofEpochMilli(epochTime * 1000)
|
|
||||||
val zonedTime = ZonedDateTime.ofInstant(instant, ZoneId.of("UTC"))
|
|
||||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
|
||||||
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -23,9 +23,6 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.GONE
|
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -5,8 +5,6 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
|
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||||
|
|
||||||
@ -35,18 +33,4 @@ abstract class SettingViewHolder(itemView: View, protected val adapter: Settings
|
|||||||
abstract override fun onClick(clicked: View)
|
abstract override fun onClick(clicked: View)
|
||||||
|
|
||||||
abstract override fun onLongClick(clicked: View): Boolean
|
abstract override fun onLongClick(clicked: View): Boolean
|
||||||
|
|
||||||
fun setStyle(isEditable: Boolean, binding: ListItemSettingBinding) {
|
|
||||||
val opacity = if (isEditable) 1.0f else 0.5f
|
|
||||||
binding.textSettingName.alpha = opacity
|
|
||||||
binding.textSettingDescription.alpha = opacity
|
|
||||||
binding.textSettingValue.alpha = opacity
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setStyle(isEditable: Boolean, binding: ListItemSettingSwitchBinding) {
|
|
||||||
binding.switchWidget.isEnabled = isEditable
|
|
||||||
val opacity = if (isEditable) 1.0f else 0.5f
|
|
||||||
binding.textSettingName.alpha = opacity
|
|
||||||
binding.textSettingDescription.alpha = opacity
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,33 +17,28 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
|||||||
override fun bind(item: SettingsItem) {
|
override fun bind(item: SettingsItem) {
|
||||||
setting = item
|
setting = item
|
||||||
binding.textSettingName.setText(item.nameId)
|
binding.textSettingName.setText(item.nameId)
|
||||||
|
binding.textSettingDescription.visibility = View.VISIBLE
|
||||||
if (item.descriptionId != 0) {
|
if (item.descriptionId != 0) {
|
||||||
binding.textSettingDescription.setText(item.descriptionId)
|
binding.textSettingDescription.setText(item.descriptionId)
|
||||||
binding.textSettingDescription.visibility = View.VISIBLE
|
} else if (item is SingleChoiceSetting) {
|
||||||
} else {
|
val resMgr = binding.textSettingDescription.context.resources
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
|
||||||
if (item is SingleChoiceSetting) {
|
|
||||||
val resMgr = binding.textSettingValue.context.resources
|
|
||||||
val values = resMgr.getIntArray(item.valuesId)
|
val values = resMgr.getIntArray(item.valuesId)
|
||||||
for (i in values.indices) {
|
for (i in values.indices) {
|
||||||
if (values[i] == item.selectedValue) {
|
if (values[i] == item.selectedValue) {
|
||||||
binding.textSettingValue.text = resMgr.getStringArray(item.choicesId)[i]
|
binding.textSettingDescription.text = resMgr.getStringArray(item.choicesId)[i]
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item is StringSingleChoiceSetting) {
|
} else if (item is StringSingleChoiceSetting) {
|
||||||
for (i in item.values!!.indices) {
|
for (i in item.values!!.indices) {
|
||||||
if (item.values[i] == item.selectedValue) {
|
if (item.values[i] == item.selectedValue) {
|
||||||
binding.textSettingValue.text = item.choices[i]
|
binding.textSettingDescription.text = item.choices[i]
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import org.yuzu.yuzu_emu.R
|
|
||||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
||||||
@ -23,14 +22,6 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.VISIBLE
|
|
||||||
binding.textSettingValue.text = String.format(
|
|
||||||
binding.textSettingValue.context.getString(R.string.value_with_units),
|
|
||||||
setting.selectedValue,
|
|
||||||
setting.units
|
|
||||||
)
|
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -22,7 +22,6 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
|
|||||||
} else {
|
} else {
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.textSettingValue.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -25,12 +25,12 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
|
|||||||
binding.textSettingDescription.text = ""
|
binding.textSettingDescription.text = ""
|
||||||
binding.textSettingDescription.visibility = View.GONE
|
binding.textSettingDescription.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
binding.switchWidget.isChecked = setting.isChecked
|
||||||
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
|
binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
|
||||||
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
adapter.onBooleanClick(item, bindingAdapterPosition, binding.switchWidget.isChecked)
|
||||||
}
|
}
|
||||||
binding.switchWidget.isChecked = setting.isChecked
|
|
||||||
|
|
||||||
setStyle(setting.isEditable, binding)
|
binding.switchWidget.isEnabled = setting.isEditable
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(clicked: View) {
|
override fun onClick(clicked: View) {
|
||||||
|
@ -19,7 +19,6 @@ import androidx.core.content.ContextCompat
|
|||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.navigation.findNavController
|
import androidx.navigation.findNavController
|
||||||
@ -33,13 +32,10 @@ import org.yuzu.yuzu_emu.adapters.SetupAdapter
|
|||||||
import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding
|
import org.yuzu.yuzu_emu.databinding.FragmentSetupBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
import org.yuzu.yuzu_emu.model.HomeViewModel
|
import org.yuzu.yuzu_emu.model.HomeViewModel
|
||||||
import org.yuzu.yuzu_emu.model.SetupCallback
|
|
||||||
import org.yuzu.yuzu_emu.model.SetupPage
|
import org.yuzu.yuzu_emu.model.SetupPage
|
||||||
import org.yuzu.yuzu_emu.model.StepState
|
|
||||||
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
import org.yuzu.yuzu_emu.ui.main.MainActivity
|
||||||
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.GameHelper
|
import org.yuzu.yuzu_emu.utils.GameHelper
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils
|
|
||||||
|
|
||||||
class SetupFragment : Fragment() {
|
class SetupFragment : Fragment() {
|
||||||
private var _binding: FragmentSetupBinding? = null
|
private var _binding: FragmentSetupBinding? = null
|
||||||
@ -116,22 +112,14 @@ class SetupFragment : Fragment() {
|
|||||||
0,
|
0,
|
||||||
false,
|
false,
|
||||||
R.string.give_permission,
|
R.string.give_permission,
|
||||||
{
|
{ permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) },
|
||||||
notificationCallback = it
|
|
||||||
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
R.string.notification_warning,
|
R.string.notification_warning,
|
||||||
R.string.notification_warning_description,
|
R.string.notification_warning_description,
|
||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
if (NotificationManagerCompat.from(requireContext())
|
NotificationManagerCompat.from(requireContext())
|
||||||
.areNotificationsEnabled()
|
.areNotificationsEnabled()
|
||||||
) {
|
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -145,22 +133,12 @@ class SetupFragment : Fragment() {
|
|||||||
R.drawable.ic_add,
|
R.drawable.ic_add,
|
||||||
true,
|
true,
|
||||||
R.string.select_keys,
|
R.string.select_keys,
|
||||||
{
|
{ mainActivity.getProdKey.launch(arrayOf("*/*")) },
|
||||||
keyCallback = it
|
|
||||||
getProdKey.launch(arrayOf("*/*"))
|
|
||||||
},
|
|
||||||
true,
|
true,
|
||||||
R.string.install_prod_keys_warning,
|
R.string.install_prod_keys_warning,
|
||||||
R.string.install_prod_keys_warning_description,
|
R.string.install_prod_keys_warning_description,
|
||||||
R.string.install_prod_keys_warning_help,
|
R.string.install_prod_keys_warning_help,
|
||||||
{
|
{ File(DirectoryInitialization.userDirectory + "/keys/prod.keys").exists() }
|
||||||
val file = File(DirectoryInitialization.userDirectory + "/keys/prod.keys")
|
|
||||||
if (file.exists()) {
|
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
@ -172,8 +150,9 @@ class SetupFragment : Fragment() {
|
|||||||
true,
|
true,
|
||||||
R.string.add_games,
|
R.string.add_games,
|
||||||
{
|
{
|
||||||
gamesDirCallback = it
|
mainActivity.getGamesDirectory.launch(
|
||||||
getGamesDirectory.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data)
|
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||||
|
)
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
R.string.add_games_warning,
|
R.string.add_games_warning,
|
||||||
@ -184,11 +163,7 @@ class SetupFragment : Fragment() {
|
|||||||
PreferenceManager.getDefaultSharedPreferences(
|
PreferenceManager.getDefaultSharedPreferences(
|
||||||
YuzuApplication.appContext
|
YuzuApplication.appContext
|
||||||
)
|
)
|
||||||
if (preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()) {
|
preferences.getString(GameHelper.KEY_GAME_PATH, "")!!.isNotEmpty()
|
||||||
StepState.COMPLETE
|
|
||||||
} else {
|
|
||||||
StepState.INCOMPLETE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -206,13 +181,6 @@ class SetupFragment : Fragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
homeViewModel.shouldPageForward.observe(viewLifecycleOwner) {
|
|
||||||
if (it) {
|
|
||||||
pageForward()
|
|
||||||
homeViewModel.setShouldPageForward(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.viewPager2.apply {
|
binding.viewPager2.apply {
|
||||||
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
|
adapter = SetupAdapter(requireActivity() as AppCompatActivity, pages)
|
||||||
offscreenPageLimit = 2
|
offscreenPageLimit = 2
|
||||||
@ -226,15 +194,15 @@ class SetupFragment : Fragment() {
|
|||||||
super.onPageSelected(position)
|
super.onPageSelected(position)
|
||||||
|
|
||||||
if (position == 1 && previousPosition == 0) {
|
if (position == 1 && previousPosition == 0) {
|
||||||
ViewUtils.showView(binding.buttonNext)
|
showView(binding.buttonNext)
|
||||||
ViewUtils.showView(binding.buttonBack)
|
showView(binding.buttonBack)
|
||||||
} else if (position == 0 && previousPosition == 1) {
|
} else if (position == 0 && previousPosition == 1) {
|
||||||
ViewUtils.hideView(binding.buttonBack)
|
hideView(binding.buttonBack)
|
||||||
ViewUtils.hideView(binding.buttonNext)
|
hideView(binding.buttonNext)
|
||||||
} else if (position == pages.size - 1 && previousPosition == pages.size - 2) {
|
} else if (position == pages.size - 1 && previousPosition == pages.size - 2) {
|
||||||
ViewUtils.hideView(binding.buttonNext)
|
hideView(binding.buttonNext)
|
||||||
} else if (position == pages.size - 2 && previousPosition == pages.size - 1) {
|
} else if (position == pages.size - 2 && previousPosition == pages.size - 1) {
|
||||||
ViewUtils.showView(binding.buttonNext)
|
showView(binding.buttonNext)
|
||||||
}
|
}
|
||||||
|
|
||||||
previousPosition = position
|
previousPosition = position
|
||||||
@ -247,8 +215,7 @@ class SetupFragment : Fragment() {
|
|||||||
|
|
||||||
// Checks if the user has completed the task on the current page
|
// Checks if the user has completed the task on the current page
|
||||||
if (currentPage.hasWarning) {
|
if (currentPage.hasWarning) {
|
||||||
val stepState = currentPage.stepCompleted.invoke()
|
if (currentPage.taskCompleted.invoke()) {
|
||||||
if (stepState != StepState.INCOMPLETE) {
|
|
||||||
pageForward()
|
pageForward()
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
@ -297,15 +264,9 @@ class SetupFragment : Fragment() {
|
|||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var notificationCallback: SetupCallback
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||||
private val permissionLauncher =
|
private val permissionLauncher =
|
||||||
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
registerForActivityResult(ActivityResultContracts.RequestPermission()) {
|
||||||
if (it) {
|
|
||||||
notificationCallback.onStepCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!it &&
|
if (!it &&
|
||||||
!shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)
|
!shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
) {
|
) {
|
||||||
@ -316,27 +277,6 @@ class SetupFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var keyCallback: SetupCallback
|
|
||||||
|
|
||||||
val getProdKey =
|
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
|
||||||
if (result != null) {
|
|
||||||
if (mainActivity.processKey(result)) {
|
|
||||||
keyCallback.onStepCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var gamesDirCallback: SetupCallback
|
|
||||||
|
|
||||||
val getGamesDirectory =
|
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
|
||||||
if (result != null) {
|
|
||||||
mainActivity.processGamesDir(result)
|
|
||||||
gamesDirCallback.onStepCompleted()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun finishSetup() {
|
private fun finishSetup() {
|
||||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
|
||||||
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
.putBoolean(Settings.PREF_FIRST_APP_LAUNCH, false)
|
||||||
@ -344,6 +284,33 @@ class SetupFragment : Fragment() {
|
|||||||
mainActivity.finishSetup(binding.root.findNavController())
|
mainActivity.finishSetup(binding.root.findNavController())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showView(view: View) {
|
||||||
|
view.apply {
|
||||||
|
alpha = 0f
|
||||||
|
visibility = View.VISIBLE
|
||||||
|
isClickable = true
|
||||||
|
}.animate().apply {
|
||||||
|
duration = 300
|
||||||
|
alpha(1f)
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideView(view: View) {
|
||||||
|
if (view.visibility == View.INVISIBLE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
view.apply {
|
||||||
|
alpha = 1f
|
||||||
|
isClickable = false
|
||||||
|
}.animate().apply {
|
||||||
|
duration = 300
|
||||||
|
alpha(0f)
|
||||||
|
}.withEndAction {
|
||||||
|
view.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun pageForward() {
|
fun pageForward() {
|
||||||
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
|
binding.viewPager2.currentItem = binding.viewPager2.currentItem + 1
|
||||||
}
|
}
|
||||||
@ -359,29 +326,15 @@ class SetupFragment : Fragment() {
|
|||||||
private fun setInsets() =
|
private fun setInsets() =
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(
|
ViewCompat.setOnApplyWindowInsetsListener(
|
||||||
binding.root
|
binding.root
|
||||||
) { _: View, windowInsets: WindowInsetsCompat ->
|
) { view: View, windowInsets: WindowInsetsCompat ->
|
||||||
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
val barInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||||
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
val cutoutInsets = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout())
|
||||||
|
view.setPadding(
|
||||||
val leftPadding = barInsets.left + cutoutInsets.left
|
barInsets.left + cutoutInsets.left,
|
||||||
val topPadding = barInsets.top + cutoutInsets.top
|
barInsets.top + cutoutInsets.top,
|
||||||
val rightPadding = barInsets.right + cutoutInsets.right
|
barInsets.right + cutoutInsets.right,
|
||||||
val bottomPadding = barInsets.bottom + cutoutInsets.bottom
|
barInsets.bottom + cutoutInsets.bottom
|
||||||
|
)
|
||||||
if (resources.getBoolean(R.bool.small_layout)) {
|
|
||||||
binding.viewPager2
|
|
||||||
.updatePadding(left = leftPadding, top = topPadding, right = rightPadding)
|
|
||||||
binding.constraintButtons
|
|
||||||
.updatePadding(left = leftPadding, right = rightPadding, bottom = bottomPadding)
|
|
||||||
} else {
|
|
||||||
binding.viewPager2.updatePadding(top = topPadding, bottom = bottomPadding)
|
|
||||||
binding.constraintButtons
|
|
||||||
.updatePadding(
|
|
||||||
left = leftPadding,
|
|
||||||
right = rightPadding,
|
|
||||||
bottom = bottomPadding
|
|
||||||
)
|
|
||||||
}
|
|
||||||
windowInsets
|
windowInsets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,6 @@ class HomeViewModel : ViewModel() {
|
|||||||
private val _statusBarShadeVisible = MutableLiveData(true)
|
private val _statusBarShadeVisible = MutableLiveData(true)
|
||||||
val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible
|
val statusBarShadeVisible: LiveData<Boolean> get() = _statusBarShadeVisible
|
||||||
|
|
||||||
private val _shouldPageForward = MutableLiveData(false)
|
|
||||||
val shouldPageForward: LiveData<Boolean> get() = _shouldPageForward
|
|
||||||
|
|
||||||
var navigatedToSetup = false
|
var navigatedToSetup = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -36,8 +33,4 @@ class HomeViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
_statusBarShadeVisible.value = visible
|
_statusBarShadeVisible.value = visible
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setShouldPageForward(pageForward: Boolean) {
|
|
||||||
_shouldPageForward.value = pageForward
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,10 @@ data class SetupPage(
|
|||||||
val buttonIconId: Int,
|
val buttonIconId: Int,
|
||||||
val leftAlignedIcon: Boolean,
|
val leftAlignedIcon: Boolean,
|
||||||
val buttonTextId: Int,
|
val buttonTextId: Int,
|
||||||
val buttonAction: (callback: SetupCallback) -> Unit,
|
val buttonAction: () -> Unit,
|
||||||
val hasWarning: Boolean,
|
val hasWarning: Boolean,
|
||||||
val warningTitleId: Int = 0,
|
val warningTitleId: Int = 0,
|
||||||
val warningDescriptionId: Int = 0,
|
val warningDescriptionId: Int = 0,
|
||||||
val warningHelpLinkId: Int = 0,
|
val warningHelpLinkId: Int = 0,
|
||||||
val stepCompleted: () -> StepState = { StepState.UNDEFINED }
|
val taskCompleted: () -> Boolean = { true }
|
||||||
)
|
)
|
||||||
|
|
||||||
interface SetupCallback {
|
|
||||||
fun onStepCompleted()
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class StepState {
|
|
||||||
COMPLETE,
|
|
||||||
INCOMPLETE,
|
|
||||||
UNDEFINED
|
|
||||||
}
|
|
||||||
|
@ -266,80 +266,73 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
|
|||||||
|
|
||||||
val getGamesDirectory =
|
val getGamesDirectory =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { result ->
|
||||||
if (result != null) {
|
if (result == null) {
|
||||||
processGamesDir(result)
|
return@registerForActivityResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contentResolver.takePersistableUriPermission(
|
||||||
|
result,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
)
|
||||||
|
|
||||||
|
// When a new directory is picked, we currently will reset the existing games
|
||||||
|
// database. This effectively means that only one game directory is supported.
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
||||||
|
.putString(GameHelper.KEY_GAME_PATH, result.toString())
|
||||||
|
.apply()
|
||||||
|
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
R.string.games_dir_selected,
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
|
||||||
|
gamesViewModel.reloadGames(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processGamesDir(result: Uri) {
|
|
||||||
contentResolver.takePersistableUriPermission(
|
|
||||||
result,
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
)
|
|
||||||
|
|
||||||
// When a new directory is picked, we currently will reset the existing games
|
|
||||||
// database. This effectively means that only one game directory is supported.
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
|
||||||
.putString(GameHelper.KEY_GAME_PATH, result.toString())
|
|
||||||
.apply()
|
|
||||||
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext,
|
|
||||||
R.string.games_dir_selected,
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
|
|
||||||
gamesViewModel.reloadGames(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
val getProdKey =
|
val getProdKey =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||||
if (result != null) {
|
if (result == null) {
|
||||||
processKey(result)
|
return@registerForActivityResult
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun processKey(result: Uri): Boolean {
|
if (FileUtil.getExtension(result) != "keys") {
|
||||||
if (FileUtil.getExtension(result) != "keys") {
|
|
||||||
MessageDialogFragment.newInstance(
|
|
||||||
R.string.reading_keys_failure,
|
|
||||||
R.string.install_prod_keys_failure_extension_description
|
|
||||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
contentResolver.takePersistableUriPermission(
|
|
||||||
result,
|
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
)
|
|
||||||
|
|
||||||
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
|
|
||||||
if (FileUtil.copyUriToInternalStorage(
|
|
||||||
applicationContext,
|
|
||||||
result,
|
|
||||||
dstPath,
|
|
||||||
"prod.keys"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
if (NativeLibrary.reloadKeys()) {
|
|
||||||
Toast.makeText(
|
|
||||||
applicationContext,
|
|
||||||
R.string.install_keys_success,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
gamesViewModel.reloadGames(true)
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
MessageDialogFragment.newInstance(
|
MessageDialogFragment.newInstance(
|
||||||
R.string.invalid_keys_error,
|
R.string.reading_keys_failure,
|
||||||
R.string.install_keys_failure_description,
|
R.string.install_prod_keys_failure_extension_description
|
||||||
R.string.dumping_keys_quickstart_link
|
|
||||||
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||||
return false
|
return@registerForActivityResult
|
||||||
|
}
|
||||||
|
|
||||||
|
contentResolver.takePersistableUriPermission(
|
||||||
|
result,
|
||||||
|
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
)
|
||||||
|
|
||||||
|
val dstPath = DirectoryInitialization.userDirectory + "/keys/"
|
||||||
|
if (FileUtil.copyUriToInternalStorage(
|
||||||
|
applicationContext,
|
||||||
|
result,
|
||||||
|
dstPath,
|
||||||
|
"prod.keys"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
if (NativeLibrary.reloadKeys()) {
|
||||||
|
Toast.makeText(
|
||||||
|
applicationContext,
|
||||||
|
R.string.install_keys_success,
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
gamesViewModel.reloadGames(true)
|
||||||
|
} else {
|
||||||
|
MessageDialogFragment.newInstance(
|
||||||
|
R.string.invalid_keys_error,
|
||||||
|
R.string.install_keys_failure_description,
|
||||||
|
R.string.dumping_keys_quickstart_link
|
||||||
|
).show(supportFragmentManager, MessageDialogFragment.TAG)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val getFirmware =
|
val getFirmware =
|
||||||
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.utils
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
|
|
||||||
object ViewUtils {
|
|
||||||
fun showView(view: View, length: Long = 300) {
|
|
||||||
view.apply {
|
|
||||||
alpha = 0f
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
isClickable = true
|
|
||||||
}.animate().apply {
|
|
||||||
duration = length
|
|
||||||
alpha(1f)
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hideView(view: View, length: Long = 300) {
|
|
||||||
if (view.visibility == View.INVISIBLE) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
view.apply {
|
|
||||||
alpha = 1f
|
|
||||||
isClickable = false
|
|
||||||
}.animate().apply {
|
|
||||||
duration = length
|
|
||||||
alpha(0f)
|
|
||||||
}.withEndAction {
|
|
||||||
view.visibility = View.INVISIBLE
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/setup_root"
|
android:id="@+id/setup_root"
|
||||||
@ -8,39 +8,33 @@
|
|||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/viewPager2"
|
android:id="@+id/viewPager2"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
android:layout_alignParentTop="true"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:layout_alignParentBottom="true"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:clipToPadding="false" />
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/constraint_buttons"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/button_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_margin="16dp"
|
||||||
android:layout_margin="8dp">
|
android:text="@string/next"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_next"
|
android:id="@+id/button_back"
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/next"
|
android:layout_margin="16dp"
|
||||||
android:visibility="invisible"
|
android:text="@string/back"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:visibility="invisible"
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
android:id="@+id/button_back"
|
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/back"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
@ -21,76 +21,45 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_weight="1">
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_title"
|
|
||||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
style="@style/TextAppearance.Material3.DisplaySmall"
|
||||||
android:layout_width="0dp"
|
android:id="@+id/text_title"
|
||||||
android:layout_height="0dp"
|
android:layout_width="match_parent"
|
||||||
android:gravity="center"
|
android:layout_height="wrap_content"
|
||||||
|
android:textAlignment="center"
|
||||||
android:textColor="?attr/colorOnSurface"
|
android:textColor="?attr/colorOnSurface"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/text_description"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_weight="2"
|
|
||||||
tools:text="@string/welcome" />
|
tools:text="@string/welcome" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/TextAppearance.Material3.TitleLarge"
|
||||||
android:id="@+id/text_description"
|
android:id="@+id/text_description"
|
||||||
style="@style/TextAppearance.Material3.TitleLarge"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_marginTop="16dp"
|
||||||
android:gravity="center"
|
android:paddingHorizontal="32dp"
|
||||||
android:textSize="20sp"
|
android:textAlignment="center"
|
||||||
android:paddingHorizontal="16dp"
|
android:textSize="26sp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
app:lineHeight="40sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
|
||||||
app:layout_constraintVertical_weight="2"
|
|
||||||
app:lineHeight="30sp"
|
|
||||||
tools:text="@string/welcome_description" />
|
tools:text="@string/welcome_description" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_confirmation"
|
|
||||||
style="@style/TextAppearance.Material3.TitleLarge"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingBottom="20dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:visibility="invisible"
|
|
||||||
android:text="@string/step_complete"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
|
||||||
app:layout_constraintVertical_weight="1"
|
|
||||||
app:lineHeight="30sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_action"
|
android:id="@+id/button_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="32dp"
|
||||||
android:layout_marginBottom="48dp"
|
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
app:iconGravity="end"
|
|
||||||
app:iconSize="24sp"
|
app:iconSize="24sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:iconGravity="end"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
|
||||||
tools:text="Get started" />
|
tools:text="Get started" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -5,16 +5,23 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/text_value"
|
android:id="@+id/text_value"
|
||||||
style="@style/TextAppearance.Material3.LabelMedium"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginBottom="@dimen/spacing_medlarge"
|
android:layout_marginBottom="@dimen/spacing_medlarge"
|
||||||
android:layout_marginTop="@dimen/spacing_medlarge"
|
android:layout_marginTop="@dimen/spacing_medlarge"
|
||||||
tools:text="75%" />
|
tools:text="75" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_units"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignTop="@+id/text_value"
|
||||||
|
android:layout_toEndOf="@+id/text_value"
|
||||||
|
tools:text="%" />
|
||||||
|
|
||||||
<com.google.android.material.slider.Slider
|
<com.google.android.material.slider.Slider
|
||||||
android:id="@+id/slider"
|
android:id="@+id/slider"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/setup_root"
|
android:id="@+id/setup_root"
|
||||||
@ -8,39 +8,35 @@
|
|||||||
|
|
||||||
<androidx.viewpager2.widget.ViewPager2
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/viewPager2"
|
android:id="@+id/viewPager2"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/button_next"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
|
android:id="@+id/button_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@+id/constraint_buttons"
|
android:layout_margin="12dp"
|
||||||
android:layout_alignParentTop="true"
|
android:text="@string/next"
|
||||||
android:clipToPadding="false" />
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/constraint_buttons"
|
style="@style/Widget.Material3.Button.TextButton"
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/button_back"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="12dp"
|
||||||
android:layout_alignParentBottom="true">
|
android:text="@string/back"
|
||||||
|
android:visibility="invisible"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
android:id="@+id/button_next"
|
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/next"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/button_back"
|
|
||||||
style="@style/Widget.Material3.Button.TextButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/back"
|
|
||||||
android:visibility="invisible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:background="?android:attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
@ -12,40 +11,31 @@
|
|||||||
android:minHeight="72dp"
|
android:minHeight="72dp"
|
||||||
android:padding="@dimen/spacing_large">
|
android:padding="@dimen/spacing_large">
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:layout_width="match_parent"
|
style="@style/TextAppearance.Material3.HeadlineMedium"
|
||||||
|
android:id="@+id/text_setting_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
app:lineHeight="28dp"
|
||||||
|
tools:text="Setting Name" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<TextView
|
||||||
android:id="@+id/text_setting_name"
|
style="@style/TextAppearance.Material3.BodySmall"
|
||||||
style="@style/TextAppearance.Material3.HeadlineMedium"
|
android:id="@+id/text_setting_description"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAlignment="viewStart"
|
android:layout_alignParentEnd="true"
|
||||||
android:textSize="16sp"
|
android:layout_alignParentStart="true"
|
||||||
app:lineHeight="22dp"
|
android:layout_alignStart="@+id/text_setting_name"
|
||||||
tools:text="Setting Name" />
|
android:layout_below="@+id/text_setting_name"
|
||||||
|
android:layout_marginTop="@dimen/spacing_small"
|
||||||
<com.google.android.material.textview.MaterialTextView
|
android:visibility="visible"
|
||||||
android:id="@+id/text_setting_description"
|
android:textAlignment="viewStart"
|
||||||
style="@style/TextAppearance.Material3.BodySmall"
|
tools:text="@string/app_disclaimer" />
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/spacing_small"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
tools:text="@string/app_disclaimer" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_setting_value"
|
|
||||||
style="@style/TextAppearance.Material3.LabelMedium"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="@dimen/spacing_small"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:text="1x" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -21,12 +21,11 @@
|
|||||||
app:layout_constraintVertical_chainStyle="spread"
|
app:layout_constraintVertical_chainStyle="spread"
|
||||||
app:layout_constraintWidth_max="220dp"
|
app:layout_constraintWidth_max="220dp"
|
||||||
app:layout_constraintWidth_min="110dp"
|
app:layout_constraintWidth_min="110dp"
|
||||||
app:layout_constraintVertical_weight="3"
|
app:layout_constraintVertical_weight="3" />
|
||||||
tools:src="@drawable/ic_notification" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
android:id="@+id/text_title"
|
android:id="@+id/text_title"
|
||||||
style="@style/TextAppearance.Material3.DisplaySmall"
|
style="@style/TextAppearance.Material3.DisplayMedium"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
@ -45,42 +44,23 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:textAlignment="center"
|
android:textAlignment="center"
|
||||||
android:textSize="20sp"
|
android:textSize="26sp"
|
||||||
android:paddingHorizontal="16dp"
|
android:paddingHorizontal="16dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
app:layout_constraintBottom_toTopOf="@+id/button_action"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
app:layout_constraintTop_toBottomOf="@+id/text_title"
|
||||||
app:layout_constraintVertical_weight="2"
|
app:layout_constraintVertical_weight="2"
|
||||||
app:lineHeight="30sp"
|
app:lineHeight="40sp"
|
||||||
tools:text="@string/welcome_description" />
|
tools:text="@string/welcome_description" />
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_confirmation"
|
|
||||||
style="@style/TextAppearance.Material3.TitleLarge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:paddingTop="24dp"
|
|
||||||
android:textAlignment="center"
|
|
||||||
android:textSize="30sp"
|
|
||||||
android:visibility="invisible"
|
|
||||||
android:text="@string/step_complete"
|
|
||||||
android:textStyle="bold"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/text_description"
|
|
||||||
app:layout_constraintVertical_weight="1"
|
|
||||||
app:lineHeight="30sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_action"
|
android:id="@+id/button_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
|
android:textSize="20sp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginBottom="48dp"
|
android:layout_marginBottom="48dp"
|
||||||
android:textSize="20sp"
|
|
||||||
app:iconGravity="end"
|
app:iconGravity="end"
|
||||||
app:iconSize="24sp"
|
app:iconSize="24sp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
<string name="back">Back</string>
|
<string name="back">Back</string>
|
||||||
<string name="add_games">Add Games</string>
|
<string name="add_games">Add Games</string>
|
||||||
<string name="add_games_description">Select your games folder</string>
|
<string name="add_games_description">Select your games folder</string>
|
||||||
<string name="step_complete">Complete!</string>
|
|
||||||
|
|
||||||
<!-- Home strings -->
|
<!-- Home strings -->
|
||||||
<string name="home_games">Games</string>
|
<string name="home_games">Games</string>
|
||||||
@ -150,7 +149,6 @@
|
|||||||
<string name="frame_limit_slider">Limit speed percent</string>
|
<string name="frame_limit_slider">Limit speed percent</string>
|
||||||
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. 100% is the normal speed. Values higher or lower will increase or decrease the speed limit.</string>
|
<string name="frame_limit_slider_description">Specifies the percentage to limit emulation speed. 100% is the normal speed. Values higher or lower will increase or decrease the speed limit.</string>
|
||||||
<string name="cpu_accuracy">CPU accuracy</string>
|
<string name="cpu_accuracy">CPU accuracy</string>
|
||||||
<string name="value_with_units">%1$s%2$s</string>
|
|
||||||
|
|
||||||
<!-- System settings strings -->
|
<!-- System settings strings -->
|
||||||
<string name="use_docked_mode">Docked Mode</string>
|
<string name="use_docked_mode">Docked Mode</string>
|
||||||
|
@ -263,23 +263,6 @@ void GDBStub::ExecuteCommand(std::string_view packet, std::vector<DebuggerAction
|
|||||||
|
|
||||||
std::vector<u8> mem(size);
|
std::vector<u8> mem(size);
|
||||||
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
|
if (system.ApplicationMemory().ReadBlock(addr, mem.data(), size)) {
|
||||||
// Restore any bytes belonging to replaced instructions.
|
|
||||||
auto it = replaced_instructions.lower_bound(addr);
|
|
||||||
for (; it != replaced_instructions.end() && it->first < addr + size; it++) {
|
|
||||||
// Get the bytes of the instruction we previously replaced.
|
|
||||||
const u32 original_bytes = it->second;
|
|
||||||
|
|
||||||
// Calculate where to start writing to the output buffer.
|
|
||||||
const size_t output_offset = it->first - addr;
|
|
||||||
|
|
||||||
// Calculate how many bytes to write.
|
|
||||||
// The loop condition ensures output_offset < size.
|
|
||||||
const size_t n = std::min<size_t>(size - output_offset, sizeof(u32));
|
|
||||||
|
|
||||||
// Write the bytes to the output buffer.
|
|
||||||
std::memcpy(mem.data() + output_offset, &original_bytes, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
SendReply(Common::HexToString(mem));
|
SendReply(Common::HexToString(mem));
|
||||||
} else {
|
} else {
|
||||||
SendReply(GDB_STUB_REPLY_ERR);
|
SendReply(GDB_STUB_REPLY_ERR);
|
||||||
|
@ -289,19 +289,6 @@ enum class GyroscopeZeroDriftMode : u32 {
|
|||||||
Tight = 2,
|
Tight = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is nn::settings::system::TouchScreenMode
|
|
||||||
enum class TouchScreenMode : u32 {
|
|
||||||
Stylus = 0,
|
|
||||||
Standard = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::TouchScreenModeForNx
|
|
||||||
enum class TouchScreenModeForNx : u8 {
|
|
||||||
UseSystemSetting,
|
|
||||||
Finger,
|
|
||||||
Heat2,
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is nn::hid::NpadStyleTag
|
// This is nn::hid::NpadStyleTag
|
||||||
struct NpadStyleTag {
|
struct NpadStyleTag {
|
||||||
union {
|
union {
|
||||||
@ -347,14 +334,6 @@ struct TouchState {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");
|
||||||
|
|
||||||
// This is nn::hid::TouchScreenConfigurationForNx
|
|
||||||
struct TouchScreenConfigurationForNx {
|
|
||||||
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
|
||||||
INSERT_PADDING_BYTES(0xF);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x10,
|
|
||||||
"TouchScreenConfigurationForNx is an invalid size");
|
|
||||||
|
|
||||||
struct NpadColor {
|
struct NpadColor {
|
||||||
u8 r{};
|
u8 r{};
|
||||||
u8 g{};
|
u8 g{};
|
||||||
@ -683,11 +662,6 @@ struct MouseState {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
|
static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size");
|
||||||
|
|
||||||
struct UniquePadId {
|
|
||||||
u64 id;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(UniquePadId) == 0x8, "UniquePadId is an invalid size");
|
|
||||||
|
|
||||||
/// Converts a NpadIdType to an array index.
|
/// Converts a NpadIdType to an array index.
|
||||||
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
constexpr size_t NpadIdTypeToIndex(NpadIdType npad_id_type) {
|
||||||
switch (npad_id_type) {
|
switch (npad_id_type) {
|
||||||
|
@ -16,6 +16,22 @@ class EmulatedConsole;
|
|||||||
namespace Service::HID {
|
namespace Service::HID {
|
||||||
class Controller_Touchscreen final : public ControllerBase {
|
class Controller_Touchscreen final : public ControllerBase {
|
||||||
public:
|
public:
|
||||||
|
// This is nn::hid::TouchScreenModeForNx
|
||||||
|
enum class TouchScreenModeForNx : u8 {
|
||||||
|
UseSystemSetting,
|
||||||
|
Finger,
|
||||||
|
Heat2,
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is nn::hid::TouchScreenConfigurationForNx
|
||||||
|
struct TouchScreenConfigurationForNx {
|
||||||
|
TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0x7);
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved
|
||||||
|
};
|
||||||
|
static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,
|
||||||
|
"TouchScreenConfigurationForNx is an invalid size");
|
||||||
|
|
||||||
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);
|
||||||
~Controller_Touchscreen() override;
|
~Controller_Touchscreen() override;
|
||||||
|
|
||||||
|
@ -2368,7 +2368,7 @@ void Hid::GetNpadCommunicationMode(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
void Hid::SetTouchScreenConfiguration(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto touchscreen_mode{rp.PopRaw<Core::HID::TouchScreenConfigurationForNx>()};
|
const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()};
|
||||||
const auto applet_resource_user_id{rp.Pop<u64>()};
|
const auto applet_resource_user_id{rp.Pop<u64>()};
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}",
|
||||||
@ -2543,8 +2543,7 @@ public:
|
|||||||
|
|
||||||
class HidSys final : public ServiceFramework<HidSys> {
|
class HidSys final : public ServiceFramework<HidSys> {
|
||||||
public:
|
public:
|
||||||
explicit HidSys(Core::System& system_)
|
explicit HidSys(Core::System& system_) : ServiceFramework{system_, "hid:sys"} {
|
||||||
: ServiceFramework{system_, "hid:sys"}, service_context{system_, "hid:sys"} {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
{31, nullptr, "SendKeyboardLockKeyEvent"},
|
||||||
@ -2569,7 +2568,7 @@ public:
|
|||||||
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
{303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
|
||||||
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
|
||||||
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
|
||||||
{306, &HidSys::GetLastActiveNpad, "GetLastActiveNpad"},
|
{306, nullptr, "GetLastActiveNpad"},
|
||||||
{307, nullptr, "GetNpadSystemExtStyle"},
|
{307, nullptr, "GetNpadSystemExtStyle"},
|
||||||
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
{308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
|
||||||
{309, nullptr, "GetNpadFullKeyGripColor"},
|
{309, nullptr, "GetNpadFullKeyGripColor"},
|
||||||
@ -2625,7 +2624,7 @@ public:
|
|||||||
{700, nullptr, "ActivateUniquePad"},
|
{700, nullptr, "ActivateUniquePad"},
|
||||||
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
{702, nullptr, "AcquireUniquePadConnectionEventHandle"},
|
||||||
{703, nullptr, "GetUniquePadIds"},
|
{703, nullptr, "GetUniquePadIds"},
|
||||||
{751, &HidSys::AcquireJoyDetachOnBluetoothOffEventHandle, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
{751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
|
||||||
{800, nullptr, "ListSixAxisSensorHandles"},
|
{800, nullptr, "ListSixAxisSensorHandles"},
|
||||||
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
{801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
|
||||||
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
{802, nullptr, "ResetSixAxisSensorCalibrationValues"},
|
||||||
@ -2651,7 +2650,7 @@ public:
|
|||||||
{830, nullptr, "SetNotificationLedPattern"},
|
{830, nullptr, "SetNotificationLedPattern"},
|
||||||
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
{831, nullptr, "SetNotificationLedPatternWithTimeout"},
|
||||||
{832, nullptr, "PrepareHidsForNotificationWake"},
|
{832, nullptr, "PrepareHidsForNotificationWake"},
|
||||||
{850, &HidSys::IsUsbFullKeyControllerEnabled, "IsUsbFullKeyControllerEnabled"},
|
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
|
||||||
{851, nullptr, "EnableUsbFullKeyController"},
|
{851, nullptr, "EnableUsbFullKeyController"},
|
||||||
{852, nullptr, "IsUsbConnected"},
|
{852, nullptr, "IsUsbConnected"},
|
||||||
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
{870, nullptr, "IsHandheldButtonPressedOnConsoleMode"},
|
||||||
@ -2683,7 +2682,7 @@ public:
|
|||||||
{1150, nullptr, "SetTouchScreenMagnification"},
|
{1150, nullptr, "SetTouchScreenMagnification"},
|
||||||
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
{1151, nullptr, "GetTouchScreenFirmwareVersion"},
|
||||||
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
{1152, nullptr, "SetTouchScreenDefaultConfiguration"},
|
||||||
{1153, &HidSys::GetTouchScreenDefaultConfiguration, "GetTouchScreenDefaultConfiguration"},
|
{1153, nullptr, "GetTouchScreenDefaultConfiguration"},
|
||||||
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
{1154, nullptr, "IsFirmwareAvailableForNotification"},
|
||||||
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
{1155, nullptr, "SetForceHandheldStyleVibration"},
|
||||||
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
{1156, nullptr, "SendConnectionTriggerWithoutTimeoutEvent"},
|
||||||
@ -2750,8 +2749,6 @@ public:
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
RegisterHandlers(functions);
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
joy_detach_event = service_context.CreateEvent("HidSys::JoyDetachEvent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -2763,66 +2760,17 @@ private:
|
|||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetLastActiveNpad(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_HID, "(STUBBED) called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushEnum(Core::HID::NpadIdType::Handheld);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
void GetUniquePadsFromNpad(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||||
|
|
||||||
|
const s64 total_entries = 0;
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
|
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
|
||||||
|
|
||||||
const std::vector<Core::HID::UniquePadId> unique_pads{};
|
|
||||||
|
|
||||||
ctx.WriteBuffer(unique_pads);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push(static_cast<u32>(unique_pads.size()));
|
rb.Push(total_entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AcquireJoyDetachOnBluetoothOffEventHandle(HLERequestContext& ctx) {
|
|
||||||
LOG_INFO(Service_AM, "called");
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushCopyObjects(joy_detach_event->GetReadableEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void IsUsbFullKeyControllerEnabled(HLERequestContext& ctx) {
|
|
||||||
const bool is_enabled = false;
|
|
||||||
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called, is_enabled={}", is_enabled);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(is_enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GetTouchScreenDefaultConfiguration(HLERequestContext& ctx) {
|
|
||||||
LOG_WARNING(Service_HID, "(STUBBED) called");
|
|
||||||
|
|
||||||
Core::HID::TouchScreenConfigurationForNx touchscreen_config{
|
|
||||||
.mode = Core::HID::TouchScreenModeForNx::Finger,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Heat2 &&
|
|
||||||
touchscreen_config.mode != Core::HID::TouchScreenModeForNx::Finger) {
|
|
||||||
touchscreen_config.mode = Core::HID::TouchScreenModeForNx::UseSystemSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 6};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushRaw(touchscreen_config);
|
|
||||||
}
|
|
||||||
|
|
||||||
Kernel::KEvent* joy_detach_event;
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoopProcess(Core::System& system) {
|
void LoopProcess(Core::System& system) {
|
||||||
|
@ -449,7 +449,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
|
|||||||
case NativeWindowScalingMode::ScaleToWindow:
|
case NativeWindowScalingMode::ScaleToWindow:
|
||||||
case NativeWindowScalingMode::ScaleCrop:
|
case NativeWindowScalingMode::ScaleCrop:
|
||||||
case NativeWindowScalingMode::NoScaleCrop:
|
case NativeWindowScalingMode::NoScaleCrop:
|
||||||
case NativeWindowScalingMode::PreserveAspectRatio:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode);
|
LOG_ERROR(Service_Nvnflinger, "unknown scaling mode {}", scaling_mode);
|
||||||
|
@ -41,7 +41,6 @@ enum class NativeWindowScalingMode : s32 {
|
|||||||
ScaleToWindow = 1,
|
ScaleToWindow = 1,
|
||||||
ScaleCrop = 2,
|
ScaleCrop = 2,
|
||||||
NoScaleCrop = 3,
|
NoScaleCrop = 3,
|
||||||
PreserveAspectRatio = 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Transform parameter for QueueBuffer
|
/// Transform parameter for QueueBuffer
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
|
|
||||||
Result DoHandshake() override {
|
Result DoHandshake() override {
|
||||||
OSStatus status = SSLHandshake(context);
|
OSStatus status = SSLHandshake(context);
|
||||||
return HandleReturn("SSLHandshake", 0, status);
|
return HandleReturn("SSLHandshake", 0, status).Code();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Read(size_t* out_size, std::span<u8> data) override {
|
Result Read(size_t* out_size, std::span<u8> data) override {
|
||||||
|
@ -476,13 +476,7 @@ NetworkInstance::~NetworkInstance() {
|
|||||||
std::optional<IPv4Address> GetHostIPv4Address() {
|
std::optional<IPv4Address> GetHostIPv4Address() {
|
||||||
const auto network_interface = Network::GetSelectedNetworkInterface();
|
const auto network_interface = Network::GetSelectedNetworkInterface();
|
||||||
if (!network_interface.has_value()) {
|
if (!network_interface.has_value()) {
|
||||||
// Only print the error once to avoid log spam
|
LOG_DEBUG(Network, "GetSelectedNetworkInterface returned no interface");
|
||||||
static bool print_error = true;
|
|
||||||
if (print_error) {
|
|
||||||
LOG_ERROR(Network, "GetSelectedNetworkInterface returned no interface");
|
|
||||||
print_error = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,14 +200,7 @@ std::optional<NetworkInterface> GetSelectedNetworkInterface() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (res == network_interfaces.end()) {
|
if (res == network_interfaces.end()) {
|
||||||
// Only print the error once to avoid log spam
|
LOG_DEBUG(Network, "Couldn't find selected interface \"{}\"", selected_network_interface);
|
||||||
static bool print_error = true;
|
|
||||||
if (print_error) {
|
|
||||||
LOG_ERROR(Network, "Couldn't find selected interface \"{}\"",
|
|
||||||
selected_network_interface);
|
|
||||||
print_error = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,8 +220,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
|||||||
ASSERT(num_textures <= MAX_TEXTURES);
|
ASSERT(num_textures <= MAX_TEXTURES);
|
||||||
ASSERT(num_images <= MAX_IMAGES);
|
ASSERT(num_images <= MAX_IMAGES);
|
||||||
|
|
||||||
const auto backend = device.GetShaderBackend();
|
const bool assembly_shaders{assembly_programs[0].handle != 0};
|
||||||
const bool assembly_shaders{backend == Settings::ShaderBackend::Glasm};
|
|
||||||
use_storage_buffers =
|
use_storage_buffers =
|
||||||
!assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks();
|
!assembly_shaders || num_storage_buffers <= device.GetMaxGLASMStorageBufferBlocks();
|
||||||
writes_global_memory &= !use_storage_buffers;
|
writes_global_memory &= !use_storage_buffers;
|
||||||
@ -231,6 +230,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
|||||||
GenerateTransformFeedbackState();
|
GenerateTransformFeedbackState();
|
||||||
}
|
}
|
||||||
const bool in_parallel = thread_worker != nullptr;
|
const bool in_parallel = thread_worker != nullptr;
|
||||||
|
const auto backend = device.GetShaderBackend();
|
||||||
auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
|
auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
|
||||||
shader_notify, backend, in_parallel,
|
shader_notify, backend, in_parallel,
|
||||||
force_context_flush](ShaderContext::Context*) mutable {
|
force_context_flush](ShaderContext::Context*) mutable {
|
||||||
@ -559,13 +559,15 @@ void GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPipeline::ConfigureTransformFeedbackImpl() const {
|
void GraphicsPipeline::ConfigureTransformFeedbackImpl() const {
|
||||||
glTransformFeedbackAttribsNV(num_xfb_attribs, xfb_attribs.data(), GL_SEPARATE_ATTRIBS);
|
glTransformFeedbackStreamAttribsNV(num_xfb_attribs, xfb_attribs.data(), num_xfb_strides,
|
||||||
|
xfb_streams.data(), GL_INTERLEAVED_ATTRIBS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPipeline::GenerateTransformFeedbackState() {
|
void GraphicsPipeline::GenerateTransformFeedbackState() {
|
||||||
// TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal
|
// TODO(Rodrigo): Inject SKIP_COMPONENTS*_NV when required. An unimplemented message will signal
|
||||||
// when this is required.
|
// when this is required.
|
||||||
GLint* cursor{xfb_attribs.data()};
|
GLint* cursor{xfb_attribs.data()};
|
||||||
|
GLint* current_stream{xfb_streams.data()};
|
||||||
|
|
||||||
for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) {
|
for (size_t feedback = 0; feedback < Maxwell::NumTransformFeedbackBuffers; ++feedback) {
|
||||||
const auto& layout = key.xfb_state.layouts[feedback];
|
const auto& layout = key.xfb_state.layouts[feedback];
|
||||||
@ -573,6 +575,15 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
|||||||
if (layout.varying_count == 0) {
|
if (layout.varying_count == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
*current_stream = static_cast<GLint>(feedback);
|
||||||
|
if (current_stream != xfb_streams.data()) {
|
||||||
|
// When stepping one stream, push the expected token
|
||||||
|
cursor[0] = GL_NEXT_BUFFER_NV;
|
||||||
|
cursor[1] = 0;
|
||||||
|
cursor[2] = 0;
|
||||||
|
cursor += XFB_ENTRY_STRIDE;
|
||||||
|
}
|
||||||
|
++current_stream;
|
||||||
|
|
||||||
const auto& locations = key.xfb_state.varyings[feedback];
|
const auto& locations = key.xfb_state.varyings[feedback];
|
||||||
std::optional<u32> current_index;
|
std::optional<u32> current_index;
|
||||||
@ -608,6 +619,7 @@ void GraphicsPipeline::GenerateTransformFeedbackState() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
num_xfb_attribs = static_cast<GLsizei>((cursor - xfb_attribs.data()) / XFB_ENTRY_STRIDE);
|
num_xfb_attribs = static_cast<GLsizei>((cursor - xfb_attribs.data()) / XFB_ENTRY_STRIDE);
|
||||||
|
num_xfb_strides = static_cast<GLsizei>(current_stream - xfb_streams.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsPipeline::WaitForBuild() {
|
void GraphicsPipeline::WaitForBuild() {
|
||||||
|
@ -154,7 +154,9 @@ private:
|
|||||||
|
|
||||||
static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
|
static constexpr std::size_t XFB_ENTRY_STRIDE = 3;
|
||||||
GLsizei num_xfb_attribs{};
|
GLsizei num_xfb_attribs{};
|
||||||
|
GLsizei num_xfb_strides{};
|
||||||
std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{};
|
std::array<GLint, 128 * XFB_ENTRY_STRIDE * Maxwell::NumTransformFeedbackBuffers> xfb_attribs{};
|
||||||
|
std::array<GLint, Maxwell::NumTransformFeedbackBuffers> xfb_streams{};
|
||||||
|
|
||||||
std::mutex built_mutex;
|
std::mutex built_mutex;
|
||||||
std::condition_variable built_condvar;
|
std::condition_variable built_condvar;
|
||||||
|
@ -326,43 +326,6 @@ std::vector<const char*> ExtensionListForVulkan(
|
|||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
void Device::RemoveExtension(bool& extension, const std::string& extension_name) {
|
|
||||||
extension = false;
|
|
||||||
loaded_extensions.erase(extension_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
|
|
||||||
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
|
||||||
LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
|
|
||||||
this->RemoveExtension(is_suitable, extension_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Feature>
|
|
||||||
void Device::RemoveExtensionFeature(bool& extension, Feature& feature,
|
|
||||||
const std::string& extension_name) {
|
|
||||||
// Unload extension.
|
|
||||||
this->RemoveExtension(extension, extension_name);
|
|
||||||
|
|
||||||
// Save sType and pNext for chain.
|
|
||||||
VkStructureType sType = feature.sType;
|
|
||||||
void* pNext = feature.pNext;
|
|
||||||
|
|
||||||
// Clear feature struct and restore chain.
|
|
||||||
feature = {};
|
|
||||||
feature.sType = sType;
|
|
||||||
feature.pNext = pNext;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Feature>
|
|
||||||
void Device::RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
|
|
||||||
const std::string& extension_name) {
|
|
||||||
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
|
||||||
LOG_WARNING(Render_Vulkan, "Removing features for unsuitable extension {}", extension_name);
|
|
||||||
this->RemoveExtensionFeature(is_suitable, feature, extension_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
|
Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
|
||||||
const vk::InstanceDispatch& dld_)
|
const vk::InstanceDispatch& dld_)
|
||||||
: instance{instance_}, dld{dld_}, physical{physical_},
|
: instance{instance_}, dld{dld_}, physical{physical_},
|
||||||
@ -434,20 +397,21 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
if (is_qualcomm || is_turnip) {
|
if (is_qualcomm || is_turnip) {
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
|
"Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
|
||||||
RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
|
extensions.custom_border_color = false;
|
||||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_qualcomm) {
|
if (is_qualcomm) {
|
||||||
must_emulate_scaled_formats = true;
|
must_emulate_scaled_formats = true;
|
||||||
|
|
||||||
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state");
|
LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
extensions.extended_dynamic_state = false;
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
|
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
|
||||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
extensions.push_descriptor = false;
|
||||||
|
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
|
|
||||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||||
// Patch the driver to enable BCn textures.
|
// Patch the driver to enable BCn textures.
|
||||||
@ -476,12 +440,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
must_emulate_scaled_formats = true;
|
must_emulate_scaled_formats = true;
|
||||||
|
|
||||||
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state");
|
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
|
extensions.extended_dynamic_state = false;
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
|
|
||||||
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2");
|
LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
|
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||||
|
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||||
|
extensions.extended_dynamic_state2 = false;
|
||||||
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_nvidia) {
|
if (is_nvidia) {
|
||||||
@ -497,7 +464,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
case NvidiaArchitecture::VoltaOrOlder:
|
case NvidiaArchitecture::VoltaOrOlder:
|
||||||
if (nv_major_version < 527) {
|
if (nv_major_version < 527) {
|
||||||
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
|
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
|
||||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
extensions.push_descriptor = false;
|
||||||
|
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -512,9 +480,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
|
if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
|
"RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state,
|
extensions.extended_dynamic_state = false;
|
||||||
features.extended_dynamic_state,
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.extended_dynamic_state2 && is_radv) {
|
if (extensions.extended_dynamic_state2 && is_radv) {
|
||||||
@ -523,9 +490,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
Render_Vulkan,
|
Render_Vulkan,
|
||||||
"RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
|
"RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||||
features.extended_dynamic_state2,
|
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||||
|
extensions.extended_dynamic_state2 = false;
|
||||||
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.extended_dynamic_state2 && is_qualcomm) {
|
if (extensions.extended_dynamic_state2 && is_qualcomm) {
|
||||||
@ -535,9 +504,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
|
// Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
|
"Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
|
||||||
RemoveExtensionFeature(extensions.extended_dynamic_state2,
|
features.extended_dynamic_state2.extendedDynamicState2 = false;
|
||||||
features.extended_dynamic_state2,
|
features.extended_dynamic_state2.extendedDynamicState2LogicOp = false;
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
|
||||||
|
extensions.extended_dynamic_state2 = false;
|
||||||
|
loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.extended_dynamic_state3 && is_radv) {
|
if (extensions.extended_dynamic_state3 && is_radv) {
|
||||||
@ -569,9 +540,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
if (is_rdna2) {
|
if (is_rdna2) {
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
|
"RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
|
||||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
|
||||||
features.vertex_input_dynamic_state,
|
extensions.vertex_input_dynamic_state = false;
|
||||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
|
if (extensions.vertex_input_dynamic_state && is_qualcomm) {
|
||||||
@ -582,9 +553,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
Render_Vulkan,
|
Render_Vulkan,
|
||||||
"Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state");
|
"Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state");
|
||||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
features.vertex_input_dynamic_state.vertexInputDynamicState = false;
|
||||||
features.vertex_input_dynamic_state,
|
extensions.vertex_input_dynamic_state = false;
|
||||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -604,8 +575,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
if (!features.shader_float16_int8.shaderFloat16) {
|
if (!features.shader_float16_int8.shaderFloat16) {
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax");
|
"AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax");
|
||||||
RemoveExtension(extensions.sampler_filter_minmax,
|
extensions.sampler_filter_minmax = false;
|
||||||
VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME);
|
loaded_extensions.erase(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,9 +584,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
const u32 version = (properties.properties.driverVersion << 3) >> 3;
|
||||||
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
|
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
|
||||||
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
|
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
|
||||||
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
|
extensions.vertex_input_dynamic_state = false;
|
||||||
features.vertex_input_dynamic_state,
|
loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
|
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
|
||||||
@ -642,7 +612,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
|||||||
// mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
|
// mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
|
||||||
LOG_WARNING(Render_Vulkan,
|
LOG_WARNING(Render_Vulkan,
|
||||||
"ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
|
"ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
|
||||||
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
extensions.push_descriptor = false;
|
||||||
|
loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_mvk) {
|
if (is_mvk) {
|
||||||
@ -1036,29 +1007,34 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
return suitable;
|
return suitable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
|
||||||
|
if (loaded_extensions.contains(extension_name) && !is_suitable) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
|
||||||
|
loaded_extensions.erase(extension_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Device::RemoveUnsuitableExtensions() {
|
void Device::RemoveUnsuitableExtensions() {
|
||||||
// VK_EXT_custom_border_color
|
// VK_EXT_custom_border_color
|
||||||
extensions.custom_border_color = features.custom_border_color.customBorderColors &&
|
extensions.custom_border_color = features.custom_border_color.customBorderColors &&
|
||||||
features.custom_border_color.customBorderColorWithoutFormat;
|
features.custom_border_color.customBorderColorWithoutFormat;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
|
RemoveExtensionIfUnsuitable(extensions.custom_border_color,
|
||||||
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_EXT_depth_clip_control
|
// VK_EXT_depth_clip_control
|
||||||
extensions.depth_clip_control = features.depth_clip_control.depthClipControl;
|
extensions.depth_clip_control = features.depth_clip_control.depthClipControl;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
|
RemoveExtensionIfUnsuitable(extensions.depth_clip_control,
|
||||||
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_EXT_extended_dynamic_state
|
// VK_EXT_extended_dynamic_state
|
||||||
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
|
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state,
|
||||||
features.extended_dynamic_state,
|
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_EXT_extended_dynamic_state2
|
// VK_EXT_extended_dynamic_state2
|
||||||
extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2;
|
extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state2,
|
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state2,
|
||||||
features.extended_dynamic_state2,
|
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_EXT_extended_dynamic_state3
|
// VK_EXT_extended_dynamic_state3
|
||||||
dynamic_state3_blending =
|
dynamic_state3_blending =
|
||||||
@ -1072,38 +1048,35 @@ void Device::RemoveUnsuitableExtensions() {
|
|||||||
extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables;
|
extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables;
|
||||||
dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3;
|
dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3;
|
||||||
dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3;
|
dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state3,
|
RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state3,
|
||||||
features.extended_dynamic_state3,
|
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
||||||
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_EXT_provoking_vertex
|
// VK_EXT_provoking_vertex
|
||||||
extensions.provoking_vertex =
|
extensions.provoking_vertex =
|
||||||
features.provoking_vertex.provokingVertexLast &&
|
features.provoking_vertex.provokingVertexLast &&
|
||||||
features.provoking_vertex.transformFeedbackPreservesProvokingVertex;
|
features.provoking_vertex.transformFeedbackPreservesProvokingVertex;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex,
|
RemoveExtensionIfUnsuitable(extensions.provoking_vertex,
|
||||||
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_KHR_shader_atomic_int64
|
// VK_KHR_shader_atomic_int64
|
||||||
extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
|
extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
|
||||||
features.shader_atomic_int64.shaderSharedInt64Atomics;
|
features.shader_atomic_int64.shaderSharedInt64Atomics;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.shader_atomic_int64, features.shader_atomic_int64,
|
RemoveExtensionIfUnsuitable(extensions.shader_atomic_int64,
|
||||||
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
|
VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_EXT_shader_demote_to_helper_invocation
|
// VK_EXT_shader_demote_to_helper_invocation
|
||||||
extensions.shader_demote_to_helper_invocation =
|
extensions.shader_demote_to_helper_invocation =
|
||||||
features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation;
|
features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.shader_demote_to_helper_invocation,
|
RemoveExtensionIfUnsuitable(extensions.shader_demote_to_helper_invocation,
|
||||||
features.shader_demote_to_helper_invocation,
|
VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
||||||
VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_EXT_subgroup_size_control
|
// VK_EXT_subgroup_size_control
|
||||||
extensions.subgroup_size_control =
|
extensions.subgroup_size_control =
|
||||||
features.subgroup_size_control.subgroupSizeControl &&
|
features.subgroup_size_control.subgroupSizeControl &&
|
||||||
properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize &&
|
properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize &&
|
||||||
properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize;
|
properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.subgroup_size_control,
|
RemoveExtensionIfUnsuitable(extensions.subgroup_size_control,
|
||||||
features.subgroup_size_control,
|
VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
|
||||||
VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_EXT_transform_feedback
|
// VK_EXT_transform_feedback
|
||||||
extensions.transform_feedback =
|
extensions.transform_feedback =
|
||||||
@ -1113,27 +1086,24 @@ void Device::RemoveUnsuitableExtensions() {
|
|||||||
properties.transform_feedback.maxTransformFeedbackBuffers > 0 &&
|
properties.transform_feedback.maxTransformFeedbackBuffers > 0 &&
|
||||||
properties.transform_feedback.transformFeedbackQueries &&
|
properties.transform_feedback.transformFeedbackQueries &&
|
||||||
properties.transform_feedback.transformFeedbackDraw;
|
properties.transform_feedback.transformFeedbackDraw;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.transform_feedback, features.transform_feedback,
|
RemoveExtensionIfUnsuitable(extensions.transform_feedback,
|
||||||
VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
|
VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
|
||||||
|
|
||||||
// VK_EXT_vertex_input_dynamic_state
|
// VK_EXT_vertex_input_dynamic_state
|
||||||
extensions.vertex_input_dynamic_state =
|
extensions.vertex_input_dynamic_state =
|
||||||
features.vertex_input_dynamic_state.vertexInputDynamicState;
|
features.vertex_input_dynamic_state.vertexInputDynamicState;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state,
|
RemoveExtensionIfUnsuitable(extensions.vertex_input_dynamic_state,
|
||||||
features.vertex_input_dynamic_state,
|
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
||||||
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
|
|
||||||
|
|
||||||
// VK_KHR_pipeline_executable_properties
|
// VK_KHR_pipeline_executable_properties
|
||||||
if (Settings::values.renderer_shader_feedback.GetValue()) {
|
if (Settings::values.renderer_shader_feedback.GetValue()) {
|
||||||
extensions.pipeline_executable_properties =
|
extensions.pipeline_executable_properties =
|
||||||
features.pipeline_executable_properties.pipelineExecutableInfo;
|
features.pipeline_executable_properties.pipelineExecutableInfo;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.pipeline_executable_properties,
|
RemoveExtensionIfUnsuitable(extensions.pipeline_executable_properties,
|
||||||
features.pipeline_executable_properties,
|
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||||
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
|
||||||
} else {
|
} else {
|
||||||
RemoveExtensionFeature(extensions.pipeline_executable_properties,
|
extensions.pipeline_executable_properties = false;
|
||||||
features.pipeline_executable_properties,
|
loaded_extensions.erase(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
||||||
VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// VK_KHR_workgroup_memory_explicit_layout
|
// VK_KHR_workgroup_memory_explicit_layout
|
||||||
@ -1143,9 +1113,8 @@ void Device::RemoveUnsuitableExtensions() {
|
|||||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess &&
|
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess &&
|
||||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess &&
|
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess &&
|
||||||
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout;
|
features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout;
|
||||||
RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout,
|
RemoveExtensionIfUnsuitable(extensions.workgroup_memory_explicit_layout,
|
||||||
features.workgroup_memory_explicit_layout,
|
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
||||||
VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Device::SetupFamilies(VkSurfaceKHR surface) {
|
void Device::SetupFamilies(VkSurfaceKHR surface) {
|
||||||
|
@ -639,17 +639,8 @@ private:
|
|||||||
|
|
||||||
// Remove extensions which have incomplete feature support.
|
// Remove extensions which have incomplete feature support.
|
||||||
void RemoveUnsuitableExtensions();
|
void RemoveUnsuitableExtensions();
|
||||||
|
|
||||||
void RemoveExtension(bool& extension, const std::string& extension_name);
|
|
||||||
void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name);
|
void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name);
|
||||||
|
|
||||||
template <typename Feature>
|
|
||||||
void RemoveExtensionFeature(bool& extension, Feature& feature,
|
|
||||||
const std::string& extension_name);
|
|
||||||
template <typename Feature>
|
|
||||||
void RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
|
|
||||||
const std::string& extension_name);
|
|
||||||
|
|
||||||
/// Sets up queue families.
|
/// Sets up queue families.
|
||||||
void SetupFamilies(VkSurfaceKHR surface);
|
void SetupFamilies(VkSurfaceKHR surface);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user