def opengl_info() -> Optional[OpenGLInfo]: # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() override = os.environ.get('QUTE_FAKE_OPENGL') if override is not None: log.init.debug("Using override {}".format(override)) vendor, version = override.split(', ', maxsplit=1) return OpenGLInfo.parse(vendor=vendor, version=version) old_context = cast(Optional[QOpenGLContext], QOpenGLContext.currentContext()) old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return OpenGLInfo(gles=True) vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("Importing version functions failed: {}".format(e)) return None if vf is None: log.init.debug("Getting version functions failed!") return None vendor = vf.glGetString(vf.GL_VENDOR) version = vf.glGetString(vf.GL_VERSION) return OpenGLInfo.parse(vendor=vendor, version=version) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() override = os.environ.get('QUTE_FAKE_OPENGL_VENDOR') if override is not None: log.init.debug("Using override {}".format(override)) return override old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("Importing version functions failed: {}".format(e)) return None if vf is None: log.init.debug("Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def offscreen_context(format): """Provide a temporary QOpenGLContext with the given QSurfaceFormat on an QOffscreenSurface.""" surface = QOffscreenSurface() surface.create() context = QOpenGLContext() context.setFormat(format) context.create() context.makeCurrent(surface) try: yield context finally: context.doneCurrent()
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("opengl_vendor: Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("opengl_vendor: Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("opengl_vendor: Importing version functions " "failed: {}".format(e)) return None if vf is None: log.init.debug("opengl_vendor: Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ # We're doing those imports here because this is only available with Qt 5.4 # or newer. from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, QOffscreenSurface) assert QApplication.instance() old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("opengl_vendor: Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("opengl_vendor: Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) vf = ctx.versionFunctions(vp) if vf is None: log.init.debug("opengl_vendor: Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ # We're doing those imports here because this is only available with Qt 5.4 # or newer. from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, QOffscreenSurface) assert QApplication.instance() assert QOpenGLContext.currentContext() is None surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() assert ok ok = ctx.makeCurrent(surface) assert ok if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) vf = ctx.versionFunctions(vp) vendor = vf.glGetString(vf.GL_VENDOR) ctx.doneCurrent() return vendor
class Window(QWindow): """ A QWindow for rendering of WindowProxy Attributes ---------- _context : QOpenGLContext Context used to render the window contents _window_proxy_id : int The WindowProxy responsible for drawing _saved_size : QSize If a resize event occurs before WindowProxy is started, then the size is saved here so that it can be set when WindowProxy is started _proxy_started_once : bool True after the first time that _of has been started """ def __init__(self, nrow=1, ncol=1, id=0): """ Create an instance of OFWindow Attributes ---------- nrow : int, optional Number of rows in WindowProxy grid, default = 1 ncol : int, optional Number of columns in WindowProxy grid, default = 1 id : int, optional Identifier for the WindowProxy (each WindowProxy should have a unique identifier), default = 0 """ super().__init__() self._context = None self._proxy_started = False self._saved_size = None self.setSurfaceType(QWindow.OpenGLSurface) self._window_proxy_id = id ofwin_createproxy(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT, nrow, ncol, True, self._window_proxy_id, False) ofwin_setmakecurrentfunction(self.make_current) ofwin_setupdatecontextfunction(self.make_current) ofwin_setswapbuffersfunction(self.swap_buffers) def exposeEvent(self, event): """ Overrides QWindow.exposeEvent() """ if not self._proxy_started: self._proxy_started = True ofwin_activate(self._window_proxy_id) ofwin_start() if self._saved_size is not None: ofwin_resizewindow(0, 0, self._saved_size.width(), self._saved_size.height()) self._saved_size = None def hideEvent(self, event): """ Overrides QWindow.exposeEvent() """ ofwin_activate(self._window_proxy_id) ofwin_signalstop() while ofwin_isrunning() == 1: QCoreApplication.processEvents(QEventLoop.AllEvents, 100) self._proxy_started = False def resizeEvent(self, event): """ Overrides QWindow.resizeEvent() """ ofwin_activate(self._window_proxy_id) if ofwin_isrunning() == 1: ofwin_resizewindow(0, 0, event.size().width(), event.size().height()) else: self._saved_size = event.size() def mousePressEvent(self, event): """ Overrides QWindow.mousePressEvent() """ ofwin_activate(self._window_proxy_id) if ofwin_isrunning() == 1: button = Window._map_qt_button_to_of_button(event.button()) if button != 0: ofwin_buttonpress(event.x(), event.y(), button) def mouseReleaseEvent(self, event): """ Overrides QWindow.mouseReleaseEvent() """ ofwin_activate(self._window_proxy_id) if ofwin_isrunning() == 1: button = Window._map_qt_button_to_of_button(event.button()) if button != 0: ofwin_buttonrelease(event.x(), event.y(), button) def mouseMoveEvent(self, event): """ Overrides QWindow.mouseMoveEvent() """ ofwin_activate(self._window_proxy_id) if ofwin_isrunning() == 1: ofwin_mousemotion(event.x(), event.y()) def keyPressEvent(self, event): """ Overrides QWindow.keyPressEvent() """ ofwin_activate(self._window_proxy_id) if ofwin_isrunning() == 1: key = Window._map_qt_key_event_to_osg_key(event) ofwin_keypress(key) # TODO call glGetError() to print any errors that may have occurred def make_current(self): """ Makes _context current for the surface of this window Returns ------- bool True if successful False if an error occurs """ success = False if self._context is None: self._context = QOpenGLContext() self._context.create() success = self._context.makeCurrent(self) if success: # self.initializeOpenGLFunctions() self._context.doneCurrent() else: return success if self._context is not None: success = self._context.makeCurrent(self) # err = glGetError() return success def swap_buffers(self): """ Swaps the buffer from _context to the surface of this window """ if self._context is not None: self._context.swapBuffers(self) @staticmethod def _map_qt_button_to_of_button(qt_button): """ Maps a Qt.MouseButton enumeration to an int for OpenFrames Parameters ---------- qt_button : Qt.MouseButton The button to map Returns ------- int The corresponding button for OpenFrames """ if qt_button == Qt.LeftButton: return 1 elif qt_button == Qt.RightButton: return 3 elif qt_button == Qt.MiddleButton: return 2 elif qt_button == Qt.BackButton: return 6 elif qt_button == Qt.ForwardButton: return 7 else: return 0 @staticmethod def _map_qt_key_event_to_osg_key(event): """ Maps a QKeyEvent to an int for OpenFrames Parameters ---------- event : PyQt5.QtGui.QKeyEvent.QKeyEvent The key event to map Returns ------- int The corresponding key code for OpenFrames """ if Qt.Key_A <= event.key() <= Qt.Key_Z: if event.modifiers() & Qt.ShiftModifier: key = event.key() else: key = event.key() + 0x20 else: key = event.key() return key
from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, QOffscreenSurface, QGuiApplication) app = QGuiApplication([]) surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() assert ok ok = ctx.makeCurrent(surface) assert ok print(f"GLES: {ctx.isOpenGLES()}") vp = QOpenGLVersionProfile() vp.setVersion(2, 0) vf = ctx.versionFunctions(vp) print(f"Vendor: {vf.glGetString(vf.GL_VENDOR)}") print(f"Renderer: {vf.glGetString(vf.GL_RENDERER)}") print(f"Version: {vf.glGetString(vf.GL_VERSION)}") print( f"Shading language version: {vf.glGetString(vf.GL_SHADING_LANGUAGE_VERSION)}" ) ctx.doneCurrent()
class OFQtGraphicsContextCallback(PyOF.GraphicsContextCallback): """ A callback that interfaces OpenFrames with PyQt's OpenGL rendering context Attributes ---------- _context : QOpenGLContext Context used to render the window contents _surface : QSurface Surface (window) on which contents will be drawn """ def __init__(self, surface): super().__init__() self._surface = surface self._context = None def swapBuffers(self): """ Swaps the front/back rendering buffer """ if self._context is not None: self._context.swapBuffers(self._surface) def makeCurrent(self): """ Makes _context current for the surface of this window Returns ------- bool True if successful False if an error occurs """ success = False if self._context is None: self._context = QOpenGLContext() self._context.create() success = self._context.makeCurrent(self._surface) if success: self._context.doneCurrent() else: return success if self._context is not None: success = self._context.makeCurrent(self._surface) # err = glGetError() return success def updateContext(self): """ Updates _context when it becomes invalid, e.g. when resizing the window Returns ------- bool True if successful False if an error occurs """ return self.makeCurrent()