mirror of
https://github.com/mupen64plus/mupen64plus-ui-python.git
synced 2025-04-02 10:51:53 -04:00
Use QOpenGLContext
This commit is contained in:
parent
234b811bd2
commit
2a9bba7adb
3 changed files with 122 additions and 103 deletions
|
@ -16,15 +16,8 @@
|
|||
|
||||
import ctypes
|
||||
|
||||
try:
|
||||
# nvidia hack
|
||||
from OpenGL import GL
|
||||
glimport = True
|
||||
except ModuleNotFoundError:
|
||||
glimport = False
|
||||
|
||||
from PyQt5.QtOpenGL import QGLFormat
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtGui import QSurfaceFormat
|
||||
|
||||
from sdl2 import SDL_WasInit, SDL_InitSubSystem, SDL_QuitSubSystem, SDL_INIT_VIDEO
|
||||
from sdl2 import SDL_GetNumDisplayModes, SDL_DisplayMode, SDL_GetDisplayMode
|
||||
|
@ -58,8 +51,6 @@ class Video:
|
|||
self.widget = None
|
||||
self.glformat = None
|
||||
self.glcontext = None
|
||||
self.major = None
|
||||
self.minor = None
|
||||
|
||||
def set_widget(self, parent, widget):
|
||||
"""Sets GL widget."""
|
||||
|
@ -69,11 +60,16 @@ class Video:
|
|||
def init(self):
|
||||
"""Initialize GL context."""
|
||||
if not self.glcontext:
|
||||
self.glformat = QGLFormat()
|
||||
self.glformat = QSurfaceFormat.defaultFormat()
|
||||
self.glformat.setVersion(3, 3)
|
||||
self.glformat.setOption(QSurfaceFormat.DeprecatedFunctions, 1)
|
||||
self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile)
|
||||
self.glformat.setRenderableType(QSurfaceFormat.OpenGL)
|
||||
self.glformat.setDepthBufferSize(24)
|
||||
self.glformat.setSwapInterval(0)
|
||||
|
||||
self.glcontext = self.widget.context()
|
||||
self.glcontext.setFormat(self.glformat)
|
||||
self.glcontext.create()
|
||||
self.parent.vidext_init.emit(self.glcontext)
|
||||
return M64ERR_SUCCESS
|
||||
|
||||
def quit(self):
|
||||
|
@ -104,13 +100,18 @@ class Video:
|
|||
|
||||
def set_mode(self, width, height, bits, mode, flags):
|
||||
"""Creates a rendering window."""
|
||||
self.widget.makeCurrent()
|
||||
if self.widget.isValid():
|
||||
if glimport:
|
||||
GL.glClearColor(0.0, 0.0, 0.0, 1.0)
|
||||
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
|
||||
self.widget.swapBuffers()
|
||||
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
|
||||
self.parent.vidext_init.emit(self.glcontext)
|
||||
while not self.parent._initialized:
|
||||
continue
|
||||
|
||||
self.glcontext.makeCurrent(self.widget)
|
||||
|
||||
if self.glcontext.isValid():
|
||||
# GL = self.glcontext.functions()
|
||||
# GL.glClearColor(0.0, 0.0, 0.0, 1.0)
|
||||
# GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
|
||||
# self.glcontext.swapBuffers(self.glcontext.surface())
|
||||
# GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
|
||||
return M64ERR_SUCCESS
|
||||
else:
|
||||
return M64ERR_SYSTEM_FAIL
|
||||
|
@ -135,7 +136,7 @@ class Video:
|
|||
def gl_get_proc(self, proc):
|
||||
"""Used to get a pointer to
|
||||
an OpenGL extension function."""
|
||||
addr = self.glcontext.getProcAddress(proc.decode())
|
||||
addr = self.glcontext.getProcAddress(proc)
|
||||
if addr is not None:
|
||||
return addr.__int__()
|
||||
else:
|
||||
|
@ -144,18 +145,18 @@ class Video:
|
|||
def gl_set_attr(self, attr, value):
|
||||
"""Sets OpenGL attributes."""
|
||||
attr_map = {
|
||||
M64P_GL_DOUBLEBUFFER: self.glformat.setDoubleBuffer,
|
||||
M64P_GL_BUFFER_SIZE: None,
|
||||
M64P_GL_DOUBLEBUFFER: self.set_doublebuffer,
|
||||
M64P_GL_BUFFER_SIZE: self.set_buffer_size,
|
||||
M64P_GL_DEPTH_SIZE: self.glformat.setDepthBufferSize,
|
||||
M64P_GL_RED_SIZE: self.glformat.setRedBufferSize,
|
||||
M64P_GL_GREEN_SIZE: self.glformat.setGreenBufferSize,
|
||||
M64P_GL_BLUE_SIZE: self.glformat.setBlueBufferSize,
|
||||
M64P_GL_ALPHA_SIZE: self.glformat.setAlphaBufferSize,
|
||||
M64P_GL_SWAP_CONTROL: self.glformat.setSwapInterval,
|
||||
M64P_GL_MULTISAMPLEBUFFERS: self.glformat.setSampleBuffers,
|
||||
M64P_GL_MULTISAMPLEBUFFERS: None,
|
||||
M64P_GL_MULTISAMPLESAMPLES: self.glformat.setSamples,
|
||||
M64P_GL_CONTEXT_MAJOR_VERSION: self.set_major,
|
||||
M64P_GL_CONTEXT_MINOR_VERSION: self.set_minor,
|
||||
M64P_GL_CONTEXT_MAJOR_VERSION: self.glformat.setMajorVersion,
|
||||
M64P_GL_CONTEXT_MINOR_VERSION: self.glformat.setMinorVersion,
|
||||
M64P_GL_CONTEXT_PROFILE_MASK: self.set_profile
|
||||
}
|
||||
|
||||
|
@ -163,24 +164,20 @@ class Video:
|
|||
if set_attr:
|
||||
set_attr(value)
|
||||
|
||||
if attr == M64P_GL_CONTEXT_MAJOR_VERSION or attr == M64P_GL_CONTEXT_MINOR_VERSION:
|
||||
if self.major and self.minor:
|
||||
self.glformat.setVersion(self.major, self.minor)
|
||||
|
||||
return M64ERR_SUCCESS
|
||||
|
||||
def gl_get_attr(self, attr, value):
|
||||
"""Gets OpenGL attributes."""
|
||||
attr_map = {
|
||||
M64P_GL_DOUBLEBUFFER: self.glformat.doubleBuffer,
|
||||
M64P_GL_BUFFER_SIZE: None,
|
||||
M64P_GL_DOUBLEBUFFER: self.get_doublebuffer,
|
||||
M64P_GL_BUFFER_SIZE: self.get_buffer_size,
|
||||
M64P_GL_DEPTH_SIZE: self.glformat.depthBufferSize,
|
||||
M64P_GL_RED_SIZE: self.glformat.redBufferSize,
|
||||
M64P_GL_GREEN_SIZE: self.glformat.greenBufferSize,
|
||||
M64P_GL_BLUE_SIZE: self.glformat.blueBufferSize,
|
||||
M64P_GL_ALPHA_SIZE: self.glformat.alphaBufferSize,
|
||||
M64P_GL_SWAP_CONTROL: self.glformat.swapInterval,
|
||||
M64P_GL_MULTISAMPLEBUFFERS: self.glformat.sampleBuffers,
|
||||
M64P_GL_MULTISAMPLEBUFFERS: None,
|
||||
M64P_GL_MULTISAMPLESAMPLES: self.glformat.samples,
|
||||
M64P_GL_CONTEXT_MAJOR_VERSION: self.glformat.majorVersion,
|
||||
M64P_GL_CONTEXT_MINOR_VERSION: self.glformat.minorVersion,
|
||||
|
@ -199,8 +196,8 @@ class Video:
|
|||
def gl_swap_buf(self):
|
||||
"""Swaps the front/back buffers after
|
||||
rendering an output video frame. """
|
||||
if self.widget.isValid():
|
||||
self.widget.swapBuffers()
|
||||
if self.glcontext.isValid():
|
||||
self.glcontext.swapBuffers(self.glcontext.surface())
|
||||
return M64ERR_SUCCESS
|
||||
|
||||
def resize_window(self, width, height):
|
||||
|
@ -210,7 +207,7 @@ class Video:
|
|||
|
||||
def gl_get_default_framebuffer(self):
|
||||
"""Gets default framebuffer."""
|
||||
return 0
|
||||
return self.glcontext.defaultFramebufferObject()
|
||||
|
||||
def init_with_render_mode(self, mode):
|
||||
return self.init()
|
||||
|
@ -221,29 +218,45 @@ class Video:
|
|||
def vk_get_instance_extensions(self, a, b):
|
||||
return M64ERR_SUCCESS
|
||||
|
||||
def set_major(self, major):
|
||||
self.major = major
|
||||
|
||||
def set_minor(self, minor):
|
||||
self.minor = minor
|
||||
|
||||
def set_profile(self, value):
|
||||
if value == M64P_GL_CONTEXT_PROFILE_CORE:
|
||||
self.glformat.setProfile(QGLFormat.CoreProfile)
|
||||
self.glformat.setProfile(QSurfaceFormat.CoreProfile)
|
||||
elif value == M64P_GL_CONTEXT_PROFILE_COMPATIBILITY:
|
||||
self.glformat.setProfile(QGLFormat.CompatibilityProfile)
|
||||
self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile)
|
||||
else:
|
||||
self.glformat.setProfile(QGLFormat.CompatibilityProfile)
|
||||
self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile)
|
||||
|
||||
def get_profile(self):
|
||||
profile = self.glformat.profile()
|
||||
if profile == QGLFormat.CoreProfile:
|
||||
if profile == QSurfaceFormat.CoreProfile:
|
||||
return M64P_GL_CONTEXT_PROFILE_CORE
|
||||
elif profile == QGLFormat.CompatibilityProfile:
|
||||
elif profile == QSurfaceFormat.CompatibilityProfile:
|
||||
return M64P_GL_CONTEXT_PROFILE_COMPATIBILITY
|
||||
else:
|
||||
return M64P_GL_CONTEXT_PROFILE_COMPATIBILITY
|
||||
|
||||
def set_doublebuffer(self, value):
|
||||
if value == 1:
|
||||
self.glformat.setSwapBehavior(QSurfaceFormat.DoubleBuffer)
|
||||
elif value == 0:
|
||||
self.glformat.setSwapBehavior(QSurfaceFormat.SingleBuffer)
|
||||
|
||||
def get_doublebuffer(self):
|
||||
if self.glformat.swapBehavior() == QSurfaceFormat.DoubleBuffer:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def set_buffer_size(self, value):
|
||||
val = int(value/4)
|
||||
self.glformat.setAlphaBufferSize(val)
|
||||
self.glformat.setRedBufferSize(val)
|
||||
self.glformat.setGreenBufferSize(val)
|
||||
self.glformat.setBlueBufferSize(val)
|
||||
|
||||
def get_buffer_size(self):
|
||||
return (self.glformat.alphaBufferSize() + self.glformat.redBufferSize() +
|
||||
self.glformat.greenBufferSize() + self.glformat.blueBufferSize())
|
||||
|
||||
video = Video()
|
||||
vidext = M64pVideoExtensionFunctions()
|
||||
vidext.Functions = 17
|
||||
|
|
|
@ -14,24 +14,60 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from PyQt5.QtCore import Qt, QMargins
|
||||
from PyQt5.QtOpenGL import QGLWidget
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QWindow, QOpenGLContext
|
||||
|
||||
from m64py.core.defs import *
|
||||
from m64py.frontend.keymap import QT2SDL2
|
||||
|
||||
|
||||
class GLWidget(QGLWidget):
|
||||
class GLWidget(QWindow):
|
||||
|
||||
def __init__(self, parent=None):
|
||||
QGLWidget.__init__(self, parent)
|
||||
self.setAttribute(Qt.WA_NativeWindow, True)
|
||||
self.setContentsMargins(QMargins())
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.parent = parent
|
||||
QWindow.__init__(self, None)
|
||||
|
||||
def showEvent(self, event):
|
||||
self.setFocus(True)
|
||||
self.setSurfaceType(QWindow.OpenGLSurface)
|
||||
self.ctx = QOpenGLContext()
|
||||
|
||||
def context(self):
|
||||
return self.ctx
|
||||
|
||||
def resizeEvent(self, event):
|
||||
size = event.size()
|
||||
self.resize(size.width(), size.height())
|
||||
width, height = int(size.width() * self.devicePixelRatio()), int(size.height() * self.devicePixelRatio())
|
||||
self.resize(width, height)
|
||||
|
||||
def paintEvent(self, event):
|
||||
pass
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self.parent.toggle_fs.emit()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if self.parent.worker.state != M64EMU_RUNNING:
|
||||
return
|
||||
|
||||
key = event.key()
|
||||
modifiers = event.modifiers()
|
||||
|
||||
if modifiers & Qt.AltModifier and (key == Qt.Key_Enter or key == Qt.Key_Return):
|
||||
self.parent.toggle_fs.emit()
|
||||
elif key == Qt.Key_F3:
|
||||
self.parent.worker.save_title()
|
||||
elif key == Qt.Key_F4:
|
||||
self.parent.worker.save_snapshot()
|
||||
else:
|
||||
try:
|
||||
sdl_key = QT2SDL2[key]
|
||||
self.parent.worker.send_sdl_keydown(sdl_key)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
if self.parent.worker.state != M64EMU_RUNNING:
|
||||
return
|
||||
|
||||
key = event.key()
|
||||
try:
|
||||
sdl_key = QT2SDL2[key]
|
||||
self.parent.worker.send_sdl_keyup(sdl_key)
|
||||
except KeyError:
|
||||
pass
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from PyQt5.QtOpenGL import QGLContext
|
||||
from PyQt5.QtGui import QKeySequence, QPixmap
|
||||
from PyQt5.QtGui import QKeySequence, QPixmap, QOpenGLContext
|
||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem
|
||||
from PyQt5.QtWidgets import QAction, QLabel, QFileDialog, QStackedWidget, QActionGroup, QSizePolicy, QDialog
|
||||
from PyQt5.QtCore import Qt, QTimer, QFileInfo, QEvent, QMargins, pyqtSignal, pyqtSlot, QThread
|
||||
from PyQt5.QtWidgets import QAction, QLabel, QFileDialog, QStackedWidget, QActionGroup, QSizePolicy, QWidget, QDialog
|
||||
from PyQt5.QtCore import Qt, QTimer, QFileInfo, QEvent, QMargins, pyqtSignal, pyqtSlot
|
||||
|
||||
from m64py.core.defs import *
|
||||
from m64py.frontend.dialogs import *
|
||||
|
@ -35,7 +34,6 @@ from m64py.frontend.settings import Settings
|
|||
from m64py.frontend.glwidget import GLWidget
|
||||
from m64py.ui.mainwindow_ui import Ui_MainWindow
|
||||
from m64py.frontend.recentfiles import RecentFiles
|
||||
from m64py.frontend.keymap import QT2SDL2
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
|
@ -50,7 +48,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
save_image = pyqtSignal(bool)
|
||||
info_dialog = pyqtSignal(str)
|
||||
archive_dialog = pyqtSignal(list)
|
||||
vidext_init = pyqtSignal(QGLContext)
|
||||
vidext_init = pyqtSignal(QOpenGLContext)
|
||||
toggle_fs = pyqtSignal()
|
||||
|
||||
def __init__(self, optparse):
|
||||
|
@ -59,6 +57,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.setupUi(self)
|
||||
self.opts, self.args = optparse
|
||||
|
||||
self._initialized = False
|
||||
self._initialize_attempt = 0
|
||||
|
||||
logview.setParent(self)
|
||||
|
@ -78,7 +77,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
|
||||
self.slots = {}
|
||||
self.stack = None
|
||||
self.glwidget = None
|
||||
self.cheats = None
|
||||
self.maximized = False
|
||||
self.widgets_height = None
|
||||
|
@ -125,36 +123,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.create_size_actions()
|
||||
self.center_widget()
|
||||
|
||||
def mouseDoubleClickEvent(self, event):
|
||||
self.toggle_fs.emit()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if self.worker.state == M64EMU_RUNNING:
|
||||
key = event.key()
|
||||
modifiers = event.modifiers()
|
||||
if modifiers & Qt.AltModifier and \
|
||||
(key == Qt.Key_Enter or key == Qt.Key_Return):
|
||||
self.toggle_fs.emit()
|
||||
elif key == Qt.Key_F3:
|
||||
self.worker.save_title()
|
||||
elif key == Qt.Key_F4:
|
||||
self.worker.save_snapshot()
|
||||
else:
|
||||
try:
|
||||
sdl_key = QT2SDL2[key]
|
||||
self.worker.send_sdl_keydown(sdl_key)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
if self.worker.state == M64EMU_RUNNING:
|
||||
key = event.key()
|
||||
try:
|
||||
sdl_key = QT2SDL2[key]
|
||||
self.worker.send_sdl_keyup(sdl_key)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def window_size_triggered(self, size):
|
||||
window_width, window_height = size
|
||||
if self.vidext and self.worker.core.get_handle():
|
||||
|
@ -173,8 +141,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
if self.worker.state in (M64EMU_RUNNING, M64EMU_PAUSED):
|
||||
self.worker.core_state_set(M64CORE_VIDEO_SIZE, video_size)
|
||||
|
||||
self.glwidget.move(int((window_width - game_width) / 2), 0)
|
||||
|
||||
self.set_sizes((window_width, window_height - self.widgets_height))
|
||||
self.settings.qset.setValue("size", (window_width, window_height - self.widgets_height))
|
||||
self.resize(window_width, window_height)
|
||||
|
@ -234,15 +200,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.stack.setPalette(palette)
|
||||
self.stack.setAutoFillBackground(True)
|
||||
|
||||
self.glwidget = GLWidget(self)
|
||||
|
||||
self.worker.video.set_widget(self, self.glwidget)
|
||||
self.setCentralWidget(self.stack)
|
||||
glwidget = GLWidget(self)
|
||||
self.worker.video.set_widget(self, glwidget)
|
||||
|
||||
self.stack.addWidget(View(self))
|
||||
self.stack.addWidget(self.glwidget)
|
||||
self.stack.addWidget(QWidget.createWindowContainer(glwidget, self))
|
||||
self.stack.setCurrentIndex(0)
|
||||
|
||||
self.setCentralWidget(self.stack)
|
||||
|
||||
def create_state_slots(self):
|
||||
"""Creates state slot actions."""
|
||||
group = QActionGroup(self)
|
||||
|
@ -273,7 +239,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
action.triggered.connect(lambda t, wi=w, he=h: self.resize(wi, he))
|
||||
|
||||
def on_vidext_init(self, context):
|
||||
context.doneCurrent()
|
||||
context.create()
|
||||
context.moveToThread(self.worker)
|
||||
self._initialized = True
|
||||
|
||||
def on_toggle_fs(self):
|
||||
if self.isFullScreen():
|
||||
|
@ -386,6 +355,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.update_status("ROM closed.")
|
||||
del self.cheats
|
||||
self.cheats = None
|
||||
self._initialized = False
|
||||
|
||||
@pyqtSlot()
|
||||
def on_actionManually_triggered(self):
|
||||
|
|
Loading…
Add table
Reference in a new issue