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-basic = Basic
preferences-change-deck-depending-on-note-type = Change deck depending on note type 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-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-hours-past-midnight = hours past midnight
preferences-interface-language = Interface language: preferences-interface-language = Interface language:
preferences-interrupt-current-audio-when-answering = Interrupt current audio when answering 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 = preferences-dark-mode-disable =
To show Anki in light mode while macOS is in dark mode, please To show Anki in light mode while macOS is in dark mode, please
see the Night Mode section of the manual. 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 appHelpSite = HELP_SITE
from aqt.main import AnkiQt # isort:skip 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 profiler: Optional[cProfile.Profile] = None
mw: Optional[AnkiQt] = None # set on init mw: Optional[AnkiQt] = None # set on init
@ -326,7 +326,7 @@ def setupGL(pm):
if isMac: if isMac:
return return
mode = pm.glMode() driver = pm.video_driver()
# work around pyqt loading wrong GL library # work around pyqt loading wrong GL library
if isLin: if isLin:
@ -366,22 +366,27 @@ def setupGL(pm):
None, None,
tr(TR.QT_MISC_ERROR), tr(TR.QT_MISC_ERROR),
tr( 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 return
else: else:
print(f"Qt {category}: {msg} {context}") print(f"Qt {category}: {msg} {context}")
qInstallMessageHandler(msgHandler) qInstallMessageHandler(msgHandler)
if mode == "auto": if driver == VideoDriver.OpenGL:
return pass
elif isLin:
os.environ["QT_XCB_FORCE_SOFTWARE_OPENGL"] = "1"
else: 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") PROFILE_CODE = os.environ.get("ANKI_PROFILE_CODE")
@ -548,11 +553,12 @@ def _run(argv=None, exec=True):
# i18n & backend # i18n & backend
backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime) 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 from aqt.utils import gfxDriverIsBroken
if gfxDriverIsBroken(): if gfxDriverIsBroken():
pm.nextGlMode() pm.set_video_driver(driver.next())
QMessageBox.critical( QMessageBox.critical(
None, None,
tr(TR.QT_MISC_ERROR), tr(TR.QT_MISC_ERROR),

View file

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

View file

@ -4,11 +4,26 @@
import anki.lang import anki.lang
import aqt import aqt
from aqt import AnkiQt from aqt import AnkiQt
from aqt.profiles import RecordingDriver from aqt.profiles import RecordingDriver, VideoDriver
from aqt.qt import * from aqt.qt import *
from aqt.utils import TR, askUser, openHelp, showInfo, showWarning, tr 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): class Preferences(QDialog):
def __init__(self, mw: AnkiQt): def __init__(self, mw: AnkiQt):
QDialog.__init__(self, mw, Qt.Window) QDialog.__init__(self, mw, Qt.Window)
@ -81,10 +96,7 @@ class Preferences(QDialog):
f = self.form f = self.form
qc = self.mw.col.conf qc = self.mw.col.conf
if isMac: self.setup_video_driver()
f.hwAccel.setVisible(False)
else:
f.hwAccel.setChecked(self.mw.pm.glMode() != "software")
f.newSpread.addItems(list(c.newCardSchedulingLabels(self.mw.col).values())) f.newSpread.addItems(list(c.newCardSchedulingLabels(self.mw.col).values()))
@ -106,19 +118,28 @@ class Preferences(QDialog):
f.newSched.setChecked(True) f.newSched.setChecked(True)
f.new_timezone.setChecked(s.new_timezone) 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): def updateCollection(self):
f = self.form f = self.form
d = self.mw.col d = self.mw.col
if not isMac: self.update_video_driver()
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))
qc = d.conf qc = d.conf
qc["addToCur"] = not f.useCurrent.currentIndex() qc["addToCur"] = not f.useCurrent.currentIndex()

View file

@ -1,6 +1,8 @@
# Copyright: Ankitects Pty Ltd and contributors # Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
from __future__ import annotations
import enum import enum
import io import io
import locale import locale
@ -37,6 +39,40 @@ class RecordingDriver(Enum):
QtAudioInput = "Qt" 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( metaConf = dict(
ver=0, ver=0,
updates=True, updates=True,
@ -535,41 +571,24 @@ create table if not exists profiles
# OpenGL # OpenGL
###################################################################### ######################################################################
def _glPath(self) -> str: def _gldriver_path(self) -> str:
return os.path.join(self.base, "gldriver") return os.path.join(self.base, "gldriver")
def glMode(self) -> str: def video_driver(self) -> VideoDriver:
if isMac: path = self._gldriver_path()
return "auto" 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() def set_video_driver(self, driver: VideoDriver) -> None:
if not os.path.exists(path): with open(self._gldriver_path(), "w") as file:
return "software" file.write(driver.value)
with open(path, "r") as file: def set_next_video_driver(self) -> None:
mode = file.read().strip() self.set_video_driver(self.video_driver().next())
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")
# Shared options # Shared options
###################################################################### ######################################################################

View file

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