4

I am trying to create a simple QQuickFrameBufferObject in order to render some custom opengl textures in Qt Quick. So I decided to test it with PySide2. Here is a simple implementation:

from PySide2.QtQuick import QQuickFramebufferObject
from PySide2.QtGui import QOpenGLFramebufferObjectFormat, QOpenGLFramebufferObject
from PySide2.QtCore import QSize, Qt

class FboRenderer(QQuickFramebufferObject.Renderer):
    def __init__(self, parent=None):
        super().__init__(parent)
        print("Creating renderer")

    def createFrameBufferObject(self, size):
        format = QOpenGLFramebufferObjectFormat()
        format.setAttachment(QOpenGLFramebufferObject.Depth)
        return QOpenGLFramebufferObject(size, format)

    def synchronize(self, item):
        print("Synchronizing")

    def render(self):
        print("Rendering")

class OpenGLCanvas(QQuickFramebufferObject):
    def __init__(self, parent=None):
        super().__init__(parent)

    def createRenderer(self):
        return FboRenderer()

Then to use this in QML I used:

    qmlRegisterType(OpenGLCanvas,"OpenGLCanvas", 1, 0, "OpenGLCanvas")
import QtQuick 2.12
import QtQuick.Window 2.12
import OpenGLCanvas 1.0

Window{
    id: win
    visible: true

    OpenGLCanvas{
        anchors.fill: parent
    }
}

Now the app runs and displays "Creating renderer" but then it crashes after a couple of seconds.

reckless
  • 741
  • 12
  • 53

1 Answers1

3

The problem is that FboRenderer() is a local variable that will be destroyed instantly, and therefore it will also destroy the C++ object causing a Segmentation fault since unreserved memory is accessed.

On the other hand you have a typo in createFrameBufferObject since it must be createFramebufferObject, that also reveals an error similar to the initial error, for this the solution is similar.

class FboRenderer(QQuickFramebufferObject.Renderer):
    def __init__(self):
        super().__init__()
        print("Creating renderer")
        self._fbos = []

    def createFramebufferObject(self, size):
        fmt = QOpenGLFramebufferObjectFormat()
        fmt.setAttachment(QOpenGLFramebufferObject.Depth)
        fbo = QOpenGLFramebufferObject(size, fmt)
        self._fbos.append(fbo)
        return fbo

    def synchronize(self, item):
        print("Synchronizing")

    def render(self):
        print("Rendering")


class OpenGLCanvas(QQuickFramebufferObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._renderer = None

    def createRenderer(self):
        if self._renderer is None:
            self.renderer = FboRenderer()
        return self.renderer
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • 2
    @daljit97 mmm, I have seen that you know C++ so the explanation will be easier. You have seen that both methods return a pointer so those responsible for managing dynamic memory is the class that invokes those methods, and they do so. Checking the source code I found `createRenderer()` is only invoked once and instead `createFramebufferObject()` is invoked n-times, so I create a single instance or use a list. – eyllanesc May 25 '20 at 13:45
  • Can you provide a c++ example of this? @eyllanesc – pennyBoy Aug 15 '22 at 01:14