add video driver enum; allow setting angle+software on mac in prefs

This commit is contained in:
Damien Elmes 2020-12-22 13:01:06 +10:00
parent b48451610f
commit 0a633160c5
7 changed files with 116 additions and 65 deletions

View File

@ -6,7 +6,6 @@ preferences-backupsanki-will-create-a-backup-of = <html><head/><body><p><span st
preferences-basic = Basic
preferences-change-deck-depending-on-note-type = Change deck depending on note type
preferences-changes-will-take-effect-when-you = Changes will take effect when you restart Anki.
preferences-hardware-acceleration-faster-may-cause-display = Hardware acceleration (faster, may cause display issues)
preferences-hours-past-midnight = hours past midnight
preferences-interface-language = Interface language:
preferences-interrupt-current-audio-when-answering = Interrupt current audio when answering

View File

@ -4,3 +4,12 @@ preferences-dark-mode-active = macOS is in dark mode
preferences-dark-mode-disable =
To show Anki in light mode while macOS is in dark mode, please
see the Night Mode section of the manual.
## Video drivers/hardware acceleration. Please avoid translating 'OpenGL' and 'ANGLE'.
preferences-video-driver = Video driver: { $driver }
preferences-video-driver-opengl-mac = OpenGL (recommended on Macs)
preferences-video-driver-software-mac = Software (not recommended)
preferences-video-driver-opengl-other = OpenGL (faster, may cause issues)
preferences-video-driver-software-other = Software (slower)
preferences-video-driver-angle = ANGLE (may work better than OpenGL)

View File

@ -37,7 +37,7 @@ appUpdate = "https://ankiweb.net/update/desktop"
appHelpSite = HELP_SITE
from aqt.main import AnkiQt # isort:skip
from aqt.profiles import ProfileManager, AnkiRestart # isort:skip
from aqt.profiles import ProfileManager, AnkiRestart, VideoDriver # isort:skip
profiler: Optional[cProfile.Profile] = None
mw: Optional[AnkiQt] = None # set on init
@ -326,7 +326,7 @@ def setupGL(pm):
if isMac:
return
mode = pm.glMode()
driver = pm.video_driver()
# work around pyqt loading wrong GL library
if isLin:
@ -366,22 +366,27 @@ def setupGL(pm):
None,
tr(TR.QT_MISC_ERROR),
tr(
TR.QT_MISC_ERROR_LOADING_GRAPHICS_DRIVER, mode=mode, context=context
TR.QT_MISC_ERROR_LOADING_GRAPHICS_DRIVER,
mode=driver.value,
context=context,
),
)
pm.nextGlMode()
pm.set_video_driver(driver.next())
return
else:
print(f"Qt {category}: {msg} {context}")
qInstallMessageHandler(msgHandler)
if mode == "auto":
return
elif isLin:
os.environ["QT_XCB_FORCE_SOFTWARE_OPENGL"] = "1"
if driver == VideoDriver.OpenGL:
pass
else:
os.environ["QT_OPENGL"] = mode
if isWin:
os.environ["QT_OPENGL"] = driver.value
elif isMac:
QCoreApplication.setAttribute(Qt.AA_UseSoftwareOpenGL)
elif isLin:
os.environ["QT_XCB_FORCE_SOFTWARE_OPENGL"] = "1"
PROFILE_CODE = os.environ.get("ANKI_PROFILE_CODE")
@ -548,11 +553,12 @@ def _run(argv=None, exec=True):
# i18n & backend
backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime)
if isLin and pm.glMode() == "auto":
driver = pm.video_driver()
if isLin and driver == VideoDriver.OpenGL:
from aqt.utils import gfxDriverIsBroken
if gfxDriverIsBroken():
pm.nextGlMode()
pm.set_video_driver(driver.next())
QMessageBox.critical(
None,
tr(TR.QT_MISC_ERROR),

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>640</width>
<height>374</height>
<height>406</height>
</rect>
</property>
<property name="windowTitle">
@ -56,11 +56,7 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="hwAccel">
<property name="text">
<string>PREFERENCES_HARDWARE_ACCELERATION_FASTER_MAY_CAUSE_DISPLAY</string>
</property>
</widget>
<widget class="QComboBox" name="video_driver"/>
</item>
<item>
<widget class="QCheckBox" name="showPlayButtons">
@ -596,7 +592,7 @@
</widget>
<tabstops>
<tabstop>lang</tabstop>
<tabstop>hwAccel</tabstop>
<tabstop>video_driver</tabstop>
<tabstop>showPlayButtons</tabstop>
<tabstop>interrupt_audio</tabstop>
<tabstop>pastePNG</tabstop>

View File

@ -4,11 +4,26 @@
import anki.lang
import aqt
from aqt import AnkiQt
from aqt.profiles import RecordingDriver
from aqt.profiles import RecordingDriver, VideoDriver
from aqt.qt import *
from aqt.utils import TR, askUser, openHelp, showInfo, showWarning, tr
def video_driver_name_for_platform(driver: VideoDriver) -> str:
if driver == VideoDriver.ANGLE:
return tr(TR.PREFERENCES_VIDEO_DRIVER_ANGLE)
elif driver == VideoDriver.Software:
if isMac:
return tr(TR.PREFERENCES_VIDEO_DRIVER_SOFTWARE_MAC)
else:
return tr(TR.PREFERENCES_VIDEO_DRIVER_SOFTWARE_OTHER)
else:
if isMac:
return tr(TR.PREFERENCES_VIDEO_DRIVER_OPENGL_MAC)
else:
return tr(TR.PREFERENCES_VIDEO_DRIVER_OPENGL_OTHER)
class Preferences(QDialog):
def __init__(self, mw: AnkiQt):
QDialog.__init__(self, mw, Qt.Window)
@ -81,10 +96,7 @@ class Preferences(QDialog):
f = self.form
qc = self.mw.col.conf
if isMac:
f.hwAccel.setVisible(False)
else:
f.hwAccel.setChecked(self.mw.pm.glMode() != "software")
self.setup_video_driver()
f.newSpread.addItems(list(c.newCardSchedulingLabels(self.mw.col).values()))
@ -106,19 +118,28 @@ class Preferences(QDialog):
f.newSched.setChecked(True)
f.new_timezone.setChecked(s.new_timezone)
def setup_video_driver(self):
self.video_drivers = VideoDriver.all_for_platform()
names = [
tr(TR.PREFERENCES_VIDEO_DRIVER, driver=video_driver_name_for_platform(d))
for d in self.video_drivers
]
self.form.video_driver.addItems(names)
self.form.video_driver.setCurrentIndex(
self.video_drivers.index(self.mw.pm.video_driver())
)
def update_video_driver(self):
new_driver = self.video_drivers[self.form.video_driver.currentIndex()]
if new_driver != self.mw.pm.video_driver():
self.mw.pm.set_video_driver(new_driver)
showInfo(tr(TR.PREFERENCES_CHANGES_WILL_TAKE_EFFECT_WHEN_YOU))
def updateCollection(self):
f = self.form
d = self.mw.col
if not isMac:
wasAccel = self.mw.pm.glMode() != "software"
wantAccel = f.hwAccel.isChecked()
if wasAccel != wantAccel:
if wantAccel:
self.mw.pm.setGlMode("auto")
else:
self.mw.pm.setGlMode("software")
showInfo(tr(TR.PREFERENCES_CHANGES_WILL_TAKE_EFFECT_WHEN_YOU))
self.update_video_driver()
qc = d.conf
qc["addToCur"] = not f.useCurrent.currentIndex()

View File

@ -1,6 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import enum
import io
import locale
@ -37,6 +39,40 @@ class RecordingDriver(Enum):
QtAudioInput = "Qt"
class VideoDriver(Enum):
OpenGL = "auto"
ANGLE = "angle"
Software = "software"
@staticmethod
def default_for_platform() -> VideoDriver:
if isMac:
return VideoDriver.OpenGL
else:
return VideoDriver.Software
def constrained_to_platform(self) -> VideoDriver:
if self == VideoDriver.ANGLE and not isWin:
return VideoDriver.Software
return self
def next(self) -> VideoDriver:
if self == VideoDriver.Software:
return VideoDriver.OpenGL
elif self == VideoDriver.OpenGL and isWin:
return VideoDriver.ANGLE
else:
return VideoDriver.Software
@staticmethod
def all_for_platform() -> List[VideoDriver]:
all = [VideoDriver.OpenGL]
if isWin:
all.append(VideoDriver.ANGLE)
all.append(VideoDriver.Software)
return all
metaConf = dict(
ver=0,
updates=True,
@ -535,41 +571,24 @@ create table if not exists profiles
# OpenGL
######################################################################
def _glPath(self) -> str:
def _gldriver_path(self) -> str:
return os.path.join(self.base, "gldriver")
def glMode(self) -> str:
if isMac:
return "auto"
def video_driver(self) -> VideoDriver:
path = self._gldriver_path()
try:
with open(path) as file:
text = file.read().strip()
return VideoDriver(text).constrained_to_platform()
except (ValueError, OSError):
return VideoDriver.default_for_platform()
path = self._glPath()
if not os.path.exists(path):
return "software"
def set_video_driver(self, driver: VideoDriver) -> None:
with open(self._gldriver_path(), "w") as file:
file.write(driver.value)
with open(path, "r") as file:
mode = file.read().strip()
if mode == "angle" and isWin:
return mode
elif mode == "software":
return mode
return "auto"
def setGlMode(self, mode) -> None:
with open(self._glPath(), "w") as file:
file.write(mode)
def nextGlMode(self) -> None:
mode = self.glMode()
if mode == "software":
self.setGlMode("auto")
elif mode == "auto":
if isWin:
self.setGlMode("angle")
else:
self.setGlMode("software")
elif mode == "angle":
self.setGlMode("software")
def set_next_video_driver(self) -> None:
self.set_video_driver(self.video_driver().next())
# Shared options
######################################################################

View File

@ -16,6 +16,7 @@ from anki import hooks
from anki.cards import Card
from anki.utils import stripHTML
from aqt import AnkiQt, gui_hooks
from aqt.profiles import VideoDriver
from aqt.qt import *
from aqt.sound import av_player, play_clicked_audio, record_audio
from aqt.theme import theme_manager
@ -138,7 +139,7 @@ class Reviewer:
def revHtml(self) -> str:
extra = self.mw.col.conf.get("reviewExtra", "")
fade = ""
if self.mw.pm.glMode() == "software":
if self.mw.pm.video_driver() == VideoDriver.Software:
fade = "<script>qFade=0;</script>"
return """
<div id=_mark>&#x2605;</div>