mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 02:34:39 +00:00
feat: Add option to lower the threshold for hardware bitmaps
This commit is contained in:
parent
27002a20ef
commit
fd73958923
7 changed files with 85 additions and 48 deletions
|
@ -51,6 +51,8 @@ import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
|||
import eu.kanade.tachiyomi.ui.source.SourcePresenter
|
||||
import eu.kanade.tachiyomi.util.manga.MangaCoverMetadata
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||
import eu.kanade.tachiyomi.util.system.launchIO
|
||||
import eu.kanade.tachiyomi.util.system.localeContext
|
||||
import eu.kanade.tachiyomi.util.system.notification
|
||||
|
@ -102,6 +104,10 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
|
|||
modules(preferenceModule(this@App), appModule(this@App), domainModule())
|
||||
}
|
||||
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||
|
||||
val scope = ProcessLifecycleOwner.get().lifecycleScope
|
||||
|
||||
basePreferences.crashReport().changes()
|
||||
.onEach {
|
||||
try {
|
||||
|
@ -110,18 +116,23 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
|
|||
// Probably already enabled/disabled
|
||||
}
|
||||
}
|
||||
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||
.launchIn(scope)
|
||||
|
||||
setupNotificationChannels()
|
||||
|
||||
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
|
||||
|
||||
MangaCoverMetadata.load()
|
||||
preferences.nightMode().changes()
|
||||
.onEach { AppCompatDelegate.setDefaultNightMode(it) }
|
||||
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||
.launchIn(scope)
|
||||
|
||||
ProcessLifecycleOwner.get().lifecycleScope.launchIO {
|
||||
basePreferences.hardwareBitmapThreshold().let { preference ->
|
||||
if (!preference.isSet()) preference.set(GLUtil.DEVICE_TEXTURE_LIMIT)
|
||||
}
|
||||
basePreferences.hardwareBitmapThreshold().changes()
|
||||
.onEach { ImageUtil.hardwareBitmapThreshold = it }
|
||||
.launchIn(scope)
|
||||
|
||||
scope.launchIO {
|
||||
with(TachiyomiWidgetManager()) { this@App.init() }
|
||||
}
|
||||
|
||||
|
@ -160,7 +171,7 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
|
|||
notificationManager.cancel(Notifications.ID_INCOGNITO_MODE)
|
||||
}
|
||||
}
|
||||
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||
.launchIn(scope)
|
||||
|
||||
initializeMigrator()
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ import eu.kanade.tachiyomi.data.coil.customDecoder
|
|||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonSubsamplingImageView
|
||||
import eu.kanade.tachiyomi.util.system.DeviceUtil
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||
import eu.kanade.tachiyomi.util.system.animatorDurationScale
|
||||
import okio.BufferedSource
|
||||
|
@ -127,7 +126,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
|||
} else {
|
||||
SubsamplingScaleImageView(context)
|
||||
}.apply {
|
||||
setMaxTileSize(GLUtil.maxTextureSize)
|
||||
setMaxTileSize(ImageUtil.hardwareBitmapThreshold)
|
||||
setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER)
|
||||
setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE)
|
||||
setMinimumTileDpi(180)
|
||||
|
@ -232,8 +231,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
|
|||
isVisible = true
|
||||
}
|
||||
is BufferedSource -> {
|
||||
// FIXME: Remove `ImageUtil.isMaxTextureSizeExceeded` after porting https://github.com/mihonapp/mihon/commit/dcddac5daaff3ec89c8507c35dc13d345ffdb6d7#diff-cbb19957efc1d319c0cdc62d5cf4b32bad5b51da21d3c67c3d4256200eb9c5d1
|
||||
if (!isWebtoon || ImageUtil.isMaxTextureSizeExceeded(data)) {
|
||||
if (!isWebtoon) {
|
||||
setHardwareConfig(!ImageUtil.isMaxTextureSizeExceeded(data))
|
||||
setImage(ImageSource.inputStream(data.inputStream()))
|
||||
isVisible = true
|
||||
|
|
|
@ -57,6 +57,7 @@ import eu.kanade.tachiyomi.ui.setting.preference
|
|||
import eu.kanade.tachiyomi.ui.setting.preferenceCategory
|
||||
import eu.kanade.tachiyomi.ui.setting.switchPreference
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import eu.kanade.tachiyomi.util.system.disableItems
|
||||
import eu.kanade.tachiyomi.util.system.e
|
||||
import eu.kanade.tachiyomi.util.system.isPackageInstalled
|
||||
|
@ -73,6 +74,7 @@ import eu.kanade.tachiyomi.util.view.setPositiveButton
|
|||
import eu.kanade.tachiyomi.util.view.setTitle
|
||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||
import java.io.File
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import kotlinx.coroutines.CoroutineStart
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
@ -393,8 +395,25 @@ class SettingsAdvancedController : SettingsLegacyController() {
|
|||
preferenceCategory {
|
||||
titleRes = MR.strings.reader
|
||||
|
||||
listPreference(activity) {
|
||||
bindTo(basePreferences.hardwareBitmapThreshold())
|
||||
titleRes = MR.strings.pref_hardware_bitmap_threshold
|
||||
|
||||
val entryMap = GLUtil.CUSTOM_TEXTURE_LIMIT_OPTIONS
|
||||
.associateWith { it.toString() }
|
||||
.toImmutableMap()
|
||||
entries = entryMap.values.toList()
|
||||
entryValues = entryMap.keys.map { it.toString() }.toList()
|
||||
|
||||
isVisible = GLUtil.DEVICE_TEXTURE_LIMIT > GLUtil.SAFE_TEXTURE_LIMIT
|
||||
|
||||
basePreferences.hardwareBitmapThreshold().changesIn(viewScope) { threshold ->
|
||||
summary = context.getString(MR.strings.pref_hardware_bitmap_threshold_summary, threshold)
|
||||
}
|
||||
}
|
||||
|
||||
preference {
|
||||
key = "pref_display_profile"
|
||||
bindTo(basePreferences.displayProfile())
|
||||
titleRes = MR.strings.pref_display_profile
|
||||
onClick {
|
||||
(activity as? MainActivity)?.showColourProfilePicker()
|
||||
|
|
|
@ -3,52 +3,54 @@ package eu.kanade.tachiyomi.util.system
|
|||
import javax.microedition.khronos.egl.EGL10
|
||||
import javax.microedition.khronos.egl.EGLConfig
|
||||
import javax.microedition.khronos.egl.EGLContext
|
||||
import kotlin.math.max
|
||||
|
||||
class GLUtil private constructor() {
|
||||
companion object {
|
||||
// Safe minimum default size
|
||||
private const val IMAGE_MAX_BITMAP_DIMENSION = 2048
|
||||
object GLUtil {
|
||||
val DEVICE_TEXTURE_LIMIT: Int by lazy {
|
||||
// Get EGL Display
|
||||
val egl = EGLContext.getEGL() as EGL10
|
||||
val display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
|
||||
|
||||
val maxTextureSize: Int
|
||||
get() {
|
||||
// Get EGL Display
|
||||
val egl = EGLContext.getEGL() as EGL10
|
||||
val display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY)
|
||||
// Initialise
|
||||
val version = IntArray(2)
|
||||
egl.eglInitialize(display, version)
|
||||
|
||||
// Initialise
|
||||
val version = IntArray(2)
|
||||
egl.eglInitialize(display, version)
|
||||
// Query total number of configurations
|
||||
val totalConfigurations = IntArray(1)
|
||||
egl.eglGetConfigs(display, null, 0, totalConfigurations)
|
||||
|
||||
// Query total number of configurations
|
||||
val totalConfigurations = IntArray(1)
|
||||
egl.eglGetConfigs(display, null, 0, totalConfigurations)
|
||||
// Query actual list configurations
|
||||
val configurationsList = arrayOfNulls<EGLConfig>(totalConfigurations[0])
|
||||
egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations)
|
||||
|
||||
// Query actual list configurations
|
||||
val configurationsList = arrayOfNulls<EGLConfig>(totalConfigurations[0])
|
||||
egl.eglGetConfigs(display, configurationsList, totalConfigurations[0], totalConfigurations)
|
||||
val textureSize = IntArray(1)
|
||||
var maximumTextureSize = 0
|
||||
|
||||
val textureSize = IntArray(1)
|
||||
var maximumTextureSize = 0
|
||||
// Iterate through all the configurations to located the maximum texture size
|
||||
for (i in 0 until totalConfigurations[0]) {
|
||||
// Only need to check for width since opengl textures are always squared
|
||||
egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize)
|
||||
|
||||
// Iterate through all the configurations to located the maximum texture size
|
||||
for (i in 0 until totalConfigurations[0]) {
|
||||
// Only need to check for width since opengl textures are always squared
|
||||
egl.eglGetConfigAttrib(display, configurationsList[i], EGL10.EGL_MAX_PBUFFER_WIDTH, textureSize)
|
||||
// Keep track of the maximum texture size
|
||||
if (maximumTextureSize < textureSize[0]) maximumTextureSize = textureSize[0]
|
||||
}
|
||||
|
||||
// Keep track of the maximum texture size
|
||||
if (maximumTextureSize < textureSize[0]) maximumTextureSize = textureSize[0]
|
||||
}
|
||||
// Release
|
||||
egl.eglTerminate(display)
|
||||
|
||||
// Release
|
||||
egl.eglTerminate(display)
|
||||
|
||||
// Return largest texture size found, or default
|
||||
return max(maximumTextureSize, IMAGE_MAX_BITMAP_DIMENSION)
|
||||
}
|
||||
// Return largest texture size found (after making it a multiplier of [Multiplier]), or default
|
||||
if (maximumTextureSize > SAFE_TEXTURE_LIMIT) {
|
||||
(maximumTextureSize / MULTIPLIER) * MULTIPLIER
|
||||
} else {
|
||||
SAFE_TEXTURE_LIMIT
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
throw InstantiationException("This class is not for instantiation")
|
||||
const val SAFE_TEXTURE_LIMIT: Int = 2048
|
||||
|
||||
val CUSTOM_TEXTURE_LIMIT_OPTIONS: List<Int> by lazy {
|
||||
val steps = ((DEVICE_TEXTURE_LIMIT / MULTIPLIER) - 1)
|
||||
List(steps) { (it + 2) * MULTIPLIER }.asReversed()
|
||||
}
|
||||
}
|
||||
|
||||
private const val MULTIPLIER: Int = 1024
|
||||
|
|
|
@ -785,9 +785,11 @@ object ImageUtil {
|
|||
fun isMaxTextureSizeExceeded(bitmap: Bitmap): Boolean =
|
||||
isMaxTextureSizeExceeded(bitmap.width, bitmap.height)
|
||||
|
||||
var hardwareBitmapThreshold: Int = GLUtil.SAFE_TEXTURE_LIMIT
|
||||
|
||||
private fun isMaxTextureSizeExceeded(width: Int, height: Int): Boolean {
|
||||
if (minOf(width, height) <= 0) return false
|
||||
|
||||
return maxOf(width, height) > GLUtil.maxTextureSize
|
||||
return maxOf(width, height) > hardwareBitmapThreshold
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import eu.kanade.tachiyomi.core.preference.Preference
|
|||
import eu.kanade.tachiyomi.core.preference.PreferenceStore
|
||||
import eu.kanade.tachiyomi.core.preference.getEnum
|
||||
import eu.kanade.tachiyomi.extension.util.ExtensionInstaller
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import yokai.i18n.MR
|
||||
|
||||
class BasePreferences(private val preferenceStore: PreferenceStore) {
|
||||
|
@ -46,4 +47,6 @@ class BasePreferences(private val preferenceStore: PreferenceStore) {
|
|||
DEFAULT(MR.strings.recents_long_tap_default),
|
||||
LAST_READ(MR.strings.recents_long_tap_last_read)
|
||||
}
|
||||
|
||||
fun hardwareBitmapThreshold() = preferenceStore.getInt("pref_hardware_bitmap_threshold", GLUtil.SAFE_TEXTURE_LIMIT)
|
||||
}
|
||||
|
|
|
@ -513,6 +513,8 @@
|
|||
<string name="pref_low">Low</string>
|
||||
<string name="pref_lowest">Lowest</string>
|
||||
<string name="pref_display_profile">Custom display profile</string>
|
||||
<string name="pref_hardware_bitmap_threshold">Custom hardware bitmap threshold</string>
|
||||
<string name="pref_hardware_bitmap_threshold_summary">If reader loads a blank image incrementally reduce the threshold.\nSelected: %s</string>
|
||||
<string name="pref_double_tap_zoom">Double tap to zoom</string>
|
||||
|
||||
<!-- Manga details -->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue