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 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)
class GLWindow(QWindow): def __init__(self): super(GLWindow, self).__init__() self.title= "GLWindow" self.setGeometry(0, 0, 640, 480) self.setupUI() def setupUI(self): self.setSurfaceType(QWindow.OpenGLSurface) self.renderctxt = QOpenGLContext(self) self.renderctxt.setFormat(self.requestedFormat()) self.renderctxt.create() self.renderctxt.makeCurrent(self) self.glfunc = self.renderctxt.versionFunctions() self.glfunc.initializeOpenGLFunctions()
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 OpenGLWindow(QWindow): def __init__(self, parent=None): super(OpenGLWindow, self).__init__(parent) self.m_update_pending = False self.m_animating = False self.m_context = None self.m_gl = None self.setSurfaceType(QWindow.OpenGLSurface) def initialize(self): pass def setAnimating(self, animating): self.m_animating = animating if animating: self.renderLater() def renderLater(self): if not self.m_update_pending: self.m_update_pending = True QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: version_profile = QOpenGLVersionProfile() version_profile.setVersion(2, 0) self.m_gl = self.m_context.versionFunctions(version_profile) self.m_gl.initializeOpenGLFunctions() self.initialize() self.render(self.m_gl) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater() def event(self, event): if event.type() == QEvent.UpdateRequest: self.renderNow() return True return super(OpenGLWindow, self).event(event) def exposeEvent(self, event): self.renderNow() def resizeEvent(self, event): self.renderNow()
def detectBestOpenGLVersion(cls): Logger.log("d", "Trying OpenGL context 4.1...") ctx = cls.setContext(4, 1, core=True) if ctx is not None: fmt = ctx.format() profile = fmt.profile() # First test: we hope for this if ((fmt.majorVersion() == 4 and fmt.minorVersion() >= 1) or (fmt.majorVersion() > 4)) and profile == QSurfaceFormat.CoreProfile: Logger.log( "d", "Yay, we got at least OpenGL 4.1 core: %s", cls.versionAsText(fmt.majorVersion(), fmt.minorVersion(), profile)) # https://riverbankcomputing.com/pipermail/pyqt/2017-January/038640.html # PyQt currently only implements 2.0, 2.1 and 4.1Core # If eg 4.5Core would be detected and used here, PyQt would not be able to handle it. major_version = 4 minor_version = 1 # CURA-6092: Check if we're not using software backed 4.1 context; A software 4.1 context # is much slower than a hardware backed 2.0 context gl_window = QWindow() gl_window.setSurfaceType(QWindow.OpenGLSurface) gl_window.showMinimized() gl_format = QSurfaceFormat() gl_format.setMajorVersion(major_version) gl_format.setMinorVersion(minor_version) gl_format.setProfile(profile) gl_context = QOpenGLContext() gl_context.setFormat(gl_format) gl_context.create() gl_context.makeCurrent(gl_window) gl_profile = QOpenGLVersionProfile() gl_profile.setVersion(major_version, minor_version) gl_profile.setProfile(profile) gl = gl_context.versionFunctions( gl_profile ) # type: Any #It's actually a protected class in PyQt that depends on the requested profile and the implementation of your graphics card. gpu_type = "Unknown" # type: str result = None if gl: result = gl.initializeOpenGLFunctions() if not result: Logger.log("e", "Could not initialize OpenGL to get gpu type") else: # WORKAROUND: Cura/#1117 Cura-packaging/12 # Some Intel GPU chipsets return a string, which is not undecodable via PyQt5. # This workaround makes the code fall back to a "Unknown" renderer in these cases. try: gpu_type = gl.glGetString(gl.GL_RENDERER) #type: str except UnicodeDecodeError: Logger.log( "e", "DecodeError while getting GL_RENDERER via glGetString!" ) Logger.log("d", "OpenGL renderer type for this OpenGL version: %s", gpu_type) if "software" in gpu_type.lower(): Logger.log( "w", "Unfortunately OpenGL 4.1 uses software rendering") else: return major_version, minor_version, QSurfaceFormat.CoreProfile else: Logger.log("d", "Failed to create OpenGL context 4.1.") # Fallback: check min spec Logger.log("d", "Trying OpenGL context 2.0...") ctx = cls.setContext(2, 0, profile=QSurfaceFormat.NoProfile) if ctx is not None: fmt = ctx.format() profile = fmt.profile() if fmt.majorVersion() >= 2 and fmt.minorVersion() >= 0: Logger.log( "d", "We got at least OpenGL context 2.0: %s", cls.versionAsText(fmt.majorVersion(), fmt.minorVersion(), profile)) return 2, 0, QSurfaceFormat.NoProfile else: Logger.log( "d", "Current OpenGL context is too low: %s" % cls.versionAsText(fmt.majorVersion(), fmt.minorVersion(), profile)) return None, None, None else: Logger.log("d", "Failed to create OpenGL context 2.0.") return None, None, None
class OpenGLWindow(QWindow): def __init__(self, parent=None): super(OpenGLWindow, self).__init__(parent) self.m_update_pending = False self.m_animating = False self.m_context = None self.m_gl = None self.setSurfaceType(QWindow.OpenGLSurface) def initialize(self): pass def setAnimating(self, animating): self.m_animating = animating if animating: self.renderLater() def renderLater(self): if not self.m_update_pending: self.m_update_pending = True QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: self.m_gl = self.m_context.versionFunctions() self.m_gl.initializeOpenGLFunctions() self.initialize() self.render(self.m_gl) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater() def event(self, event): if event.type() == QEvent.UpdateRequest: self.renderNow() return True return super(OpenGLWindow, self).event(event) def exposeEvent(self, event): self.renderNow() def resizeEvent(self, event): self.renderNow()
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 OpenGLWindow(QWindow): def __init__(self, parent=None): super(OpenGLWindow, self).__init__(parent) self.m_update_pending = False self.m_animating = False self.m_context = None self.m_device = None self.m_gl = None self.logger = None self.setSurfaceType(QWindow.OpenGLSurface) def initialize(self, gl): pass def setAnimating(self, animating): self.m_animating = animating if animating: self.renderLater() def renderLater(self): if not self.m_update_pending: self.m_update_pending = True QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) def paint(self, painter): pass def render(self, gl): pass def addGlFunctuins(self, GL, functions): for function, arguments in functions.items(): GL[function].restype = None GL[function].argtypes = arguments setattr(self.m_gl, function, GL[function]) @exitOnKeyboardInterrupt def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: # Sorry, no support for higher versions for now. profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self.m_gl = self.m_context.versionFunctions(profile) self.m_gl.initializeOpenGLFunctions() #print(self.m_context.hasExtension('GL_EXT_framebuffer_object')) #print(self.m_context.hasExtension('GL_ARB_texture_float')) #print(*sorted(self.m_context.extensions()), sep='\n') # Small hack. Guess noone mind? import ctypes import ctypes.util GL = ctypes.CDLL(ctypes.util.find_library('GL')) self.addGlFunctuins(GL, { 'glFramebufferTexture2D': (ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_int) }) self.logger = QOpenGLDebugLogger() self.logger.initialize() self.logger.loggedMessages() self.logger.messageLogged.connect(self.handleLoggedMassage) self.logger.startLogging() self.initialize(self.m_gl) if not self.m_device: self.m_device = QOpenGLPaintDevice() self.m_gl.glClear(self.m_gl.GL_COLOR_BUFFER_BIT | self.m_gl.GL_DEPTH_BUFFER_BIT); self.m_device.setSize(self.size()) painter = QPainter(self.m_device) painter.beginNativePainting() self.render(self.m_gl) painter.endNativePainting() self.paint(painter) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater() def handleLoggedMassage(self, message): # This three really annoyng and brings no useful info =\ if not (message.message().find('Use glDrawRangeElements() to avoid this.') > -1 or message.message().find('CPU mapping a busy miptree') > -1 or message.message().find('Flushing before mapping a referenced bo.') > -1 ): print(message.message().strip()) def event(self, event): if event.type() == QEvent.UpdateRequest: self.renderNow() return True return super(OpenGLWindow, self).event(event) def exposeEvent(self, event): self.renderNow() def resizeEvent(self, event): self.renderNow()
def init(): ''' Startup initialisation of OpenGL. ''' if gl is None: version, profile = get_profile_settings() # Initialise application-wide GL version fmt = QSurfaceFormat() fmt.setVersion(*version) # profile = QSurfaceFormat.CoreProfile if sys.platform == 'darwin' else QSurfaceFormat.CompatibilityProfile fmt.setProfile(profile or QSurfaceFormat.CompatibilityProfile) QSurfaceFormat.setDefaultFormat(fmt) if profile is not None: # Use a dummy context to get GL functions glprofile = QOpenGLVersionProfile(fmt) ctx = QOpenGLContext() globals()['gl'] = ctx.versionFunctions(glprofile) # Check and set OpenGL capabilities if not glprofile.hasProfiles(): raise RuntimeError( 'No OpenGL version >= 3.3 support detected for this system!' ) else: # If profile was none, PyQt5 is not shipped with any OpenGL function modules. Use PyOpenGL instead print( "Couldn't find OpenGL functions in Qt. Falling back to PyOpenGL" ) globals()['gl'] = importlib.import_module('OpenGL.GL') globals()['_glvar_sizes'] = { gl.GL_FLOAT: 1, gl.GL_FLOAT_VEC2: 2, gl.GL_FLOAT_VEC3: 3, gl.GL_FLOAT_VEC4: 4, gl.GL_FLOAT_MAT2: 4, gl.GL_FLOAT_MAT3: 9, gl.GL_FLOAT_MAT4: 16, gl.GL_FLOAT_MAT2x3: 6, gl.GL_FLOAT_MAT2x4: 8, gl.GL_FLOAT_MAT3x2: 6, gl.GL_FLOAT_MAT3x4: 12, gl.GL_FLOAT_MAT4x2: 8, gl.GL_FLOAT_MAT4x3: 12, gl.GL_INT: 1, gl.GL_INT_VEC2: 2, gl.GL_INT_VEC3: 3, gl.GL_INT_VEC4: 4, gl.GL_UNSIGNED_INT: 1, gl.GL_UNSIGNED_INT_VEC2: 2, gl.GL_UNSIGNED_INT_VEC3: 3, gl.GL_UNSIGNED_INT_VEC4: 4, gl.GL_DOUBLE: 1, gl.GL_DOUBLE_VEC2: 2, gl.GL_DOUBLE_VEC3: 3, gl.GL_DOUBLE_VEC4: 4, gl.GL_DOUBLE_MAT2: 4, gl.GL_DOUBLE_MAT3: 9, gl.GL_DOUBLE_MAT4: 16, gl.GL_DOUBLE_MAT2x3: 6, gl.GL_DOUBLE_MAT2x4: 8, gl.GL_DOUBLE_MAT3x2: 6, gl.GL_DOUBLE_MAT3x4: 12, gl.GL_DOUBLE_MAT4x2: 8, gl.GL_DOUBLE_MAT4x3: 12 } return gl