@ZeroZero Thanks for your response below is my code refactored for QT6 . I have set q->setGraphicsApi(QSGRendererInterface::OpenGL); here previously .
Was getting the below error.
error:
QQuickWindow: No render target (neither swapchain nor custom target was provided)
Moving that to main as you mentioned still get the same error with some additional .
int main(int argc, char *argv[])
{
{
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
QCoreApplication app(argc, argv);
....
........................................................................................
Error:
Framebuffer incomplete: 0x8cd6
Failed to build texture render target for QQuickRenderTarget
QQuickWindow: No render target (neither swapchain nor custom target was provided)
Refactored Code for QT6 that I am struggling to make it work
#include "fboquickwindow.h"
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QQuickRenderControl>
#include <QTimer>
#include <QQuickRenderTarget>
class FboQuickWindowPrivate : public QObject
{
Q_OBJECT
Q_DECLARE_PUBLIC(FboQuickWindow)
Q_DISABLE_COPY(FboQuickWindowPrivate)
public:
FboQuickWindowPrivate(FboQuickWindow *q_ptr);
~FboQuickWindowPrivate();
static FboQuickWindowPrivate *create(FboQuickWindowPrivate *&d_ptr, FboQuickWindow *q_ptr);
public slots:
void sceneGraphInitialized();
void sceneGraphInvalidated();
void renderRequested();
void sceneChanged();
public:
void render();
public:
QOpenGLContext *context;
QOffscreenSurface *offscreenSurface;
QQuickRenderControl *renderControl;
QOpenGLFramebufferObject *fbo;
bool needsPolishAndSync;
QTimer updateTimer;
FboQuickWindow * const q_ptr;
};
FboQuickWindowPrivate::FboQuickWindowPrivate(FboQuickWindow *q_ptr) :
fbo(0),
needsPolishAndSync(false),
q_ptr(q_ptr)
{
updateTimer.setSingleShot(true);
updateTimer.setInterval(5);
connect(&updateTimer, &QTimer::timeout, this, &FboQuickWindowPrivate::render);
renderControl = new QQuickRenderControl;
connect(renderControl, &QQuickRenderControl::renderRequested, this, &FboQuickWindowPrivate::renderRequested);
connect(renderControl, &QQuickRenderControl::sceneChanged, this, &FboQuickWindowPrivate::sceneChanged);
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
context = new QOpenGLContext;
context->setFormat(format);
context->create();
offscreenSurface = new QOffscreenSurface;
offscreenSurface->setFormat(context->format());
offscreenSurface->create();
}
FboQuickWindowPrivate::~FboQuickWindowPrivate()
{
context->makeCurrent(offscreenSurface);
delete renderControl;
context->doneCurrent();
delete offscreenSurface;
delete context;
}
FboQuickWindowPrivate *FboQuickWindowPrivate::create(FboQuickWindowPrivate *&d_ptr,
FboQuickWindow *q_ptr)
{
return (d_ptr = new FboQuickWindowPrivate(q_ptr));
}
void FboQuickWindowPrivate::sceneGraphInitialized()
{
Q_Q(FboQuickWindow);
Q_ASSERT(context);
Q_ASSERT(!fbo);
fbo = new QOpenGLFramebufferObject(QSize(1, 1).expandedTo(q->size()),
QOpenGLFramebufferObject::CombinedDepthStencil);
QQuickRenderTarget rt = QQuickRenderTarget::fromOpenGLRenderBuffer(fbo->handle(), fbo->size() ,1);
q->setGraphicsApi(QSGRendererInterface::OpenGL);
q->setRenderTarget(rt);
}
void FboQuickWindowPrivate::sceneGraphInvalidated()
{
delete fbo;
fbo = 0;
}
void FboQuickWindowPrivate::renderRequested()
{
if (!updateTimer.isActive())
updateTimer.start();
}
void FboQuickWindowPrivate::sceneChanged()
{
needsPolishAndSync = true;
if (!updateTimer.isActive())
updateTimer.start();
}
void FboQuickWindowPrivate::render()
{
Q_Q(FboQuickWindow);
if (!context->makeCurrent(offscreenSurface))
return;
// if (needsPolishAndSync) {
// renderControl->polishItems();
// renderControl->beginFrame();
// renderControl->sync();
// renderControl->endFrame();
// needsPolishAndSync = false;
// }
q->beginExternalCommands(); // Begin external OpenGL commands
renderControl->beginFrame();
renderControl->sync();
renderControl->render();
renderControl->endFrame();
q->endExternalCommands(); // End external OpenGL commands
// q->resetOpenGLState();
//QOpenGLFramebufferObject::bindDefault();
//context->functions()->glFlush();
emit q->sceneRendered();
}
FboQuickWindow::FboQuickWindow() :
QQuickWindow(FboQuickWindowPrivate::create(d_ptr, this)->renderControl)
{
Q_D(FboQuickWindow);
connect(this, &QQuickWindow::sceneGraphInitialized, d, &FboQuickWindowPrivate::sceneGraphInitialized);
connect(this, &QQuickWindow::sceneGraphInvalidated, d, &FboQuickWindowPrivate::sceneGraphInvalidated);
d->context->makeCurrent(d->offscreenSurface);
d->renderControl->initialize();
// if (!d->renderControl->initialize())
// qWarning("Failed to initialize redirected Qt Quick rendering");
d->context->doneCurrent();
}
FboQuickWindow::~FboQuickWindow()
{
delete d_ptr;
}
QImage FboQuickWindow::grab() const
{
Q_D(const FboQuickWindow);
return d->renderControl->window()->grabWindow();
}
void FboQuickWindow::resize(const QSize &newSize)
{
QResizeEvent event(size(), newSize);
setGeometry(0, 0, newSize.width(), newSize.height());
resizeEvent(&event);
}
void FboQuickWindow::resize(int w, int h)
{
resize(QSize(w, h));
}
void FboQuickWindow::resizeEvent(QResizeEvent *event)
{
Q_D(FboQuickWindow);
QQuickWindow::resizeEvent(event);
Q_ASSERT(d->context);
if (d->context->makeCurrent(d->offscreenSurface)) {
d->sceneGraphInvalidated();
d->sceneGraphInitialized();
d->context->doneCurrent();
}
}
#include "fboquickwindow.moc"
And here is the original code that works with QT5
#include "fboquickwindow.h"
#include <QOffscreenSurface>
#include <QOpenGLContext>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QQuickRenderControl>
#include <QTimer>
class FboQuickWindowPrivate : public QObject
{
Q_OBJECT
Q_DECLARE_PUBLIC(FboQuickWindow)
Q_DISABLE_COPY(FboQuickWindowPrivate)
public:
FboQuickWindowPrivate(FboQuickWindow *q_ptr);
~FboQuickWindowPrivate();
static FboQuickWindowPrivate *create(FboQuickWindowPrivate *&d_ptr, FboQuickWindow *q_ptr);
public slots:
void sceneGraphInitialized();
void sceneGraphInvalidated();
void renderRequested();
void sceneChanged();
public:
void render();
public:
QOpenGLContext *context;
QOffscreenSurface *offscreenSurface;
QQuickRenderControl *renderControl;
QOpenGLFramebufferObject *fbo;
bool needsPolishAndSync;
QTimer updateTimer;
FboQuickWindow * const q_ptr;
};
FboQuickWindowPrivate::FboQuickWindowPrivate(FboQuickWindow *q_ptr) :
fbo(0),
needsPolishAndSync(false),
q_ptr(q_ptr)
{
updateTimer.setSingleShot(true);
updateTimer.setInterval(5);
connect(&updateTimer, &QTimer::timeout, this, &FboQuickWindowPrivate::render);
renderControl = new QQuickRenderControl;
connect(renderControl, &QQuickRenderControl::renderRequested, this, &FboQuickWindowPrivate::renderRequested);
connect(renderControl, &QQuickRenderControl::sceneChanged, this, &FboQuickWindowPrivate::sceneChanged);
QSurfaceFormat format;
format.setDepthBufferSize(16);
format.setStencilBufferSize(8);
context = new QOpenGLContext;
context->setFormat(format);
context->create();
offscreenSurface = new QOffscreenSurface;
offscreenSurface->setFormat(context->format());
offscreenSurface->create();
}
FboQuickWindowPrivate::~FboQuickWindowPrivate()
{
context->makeCurrent(offscreenSurface);
delete renderControl;
context->doneCurrent();
delete offscreenSurface;
delete context;
}
FboQuickWindowPrivate *FboQuickWindowPrivate::create(FboQuickWindowPrivate *&d_ptr,
FboQuickWindow *q_ptr)
{
return (d_ptr = new FboQuickWindowPrivate(q_ptr));
}
void FboQuickWindowPrivate::sceneGraphInitialized()
{
Q_Q(FboQuickWindow);
Q_ASSERT(context);
Q_ASSERT(!fbo);
fbo = new QOpenGLFramebufferObject(QSize(1, 1).expandedTo(q->size()),
QOpenGLFramebufferObject::CombinedDepthStencil);
q->setRenderTarget(fbo);
}
void FboQuickWindowPrivate::sceneGraphInvalidated()
{
delete fbo;
fbo = 0;
}
void FboQuickWindowPrivate::renderRequested()
{
if (!updateTimer.isActive())
updateTimer.start();
}
void FboQuickWindowPrivate::sceneChanged()
{
needsPolishAndSync = true;
if (!updateTimer.isActive())
updateTimer.start();
}
void FboQuickWindowPrivate::render()
{
Q_Q(FboQuickWindow);
if (!context->makeCurrent(offscreenSurface))
return;
if (needsPolishAndSync) {
renderControl->polishItems();
renderControl->sync();
needsPolishAndSync = false;
}
renderControl->render();
q->resetOpenGLState();
QOpenGLFramebufferObject::bindDefault();
context->functions()->glFlush();
emit q->sceneRendered();
}
FboQuickWindow::FboQuickWindow() :
QQuickWindow(FboQuickWindowPrivate::create(d_ptr, this)->renderControl)
{
Q_D(FboQuickWindow);
connect(this, &QQuickWindow::sceneGraphInitialized, d, &FboQuickWindowPrivate::sceneGraphInitialized);
connect(this, &QQuickWindow::sceneGraphInvalidated, d, &FboQuickWindowPrivate::sceneGraphInvalidated);
d->context->makeCurrent(d->offscreenSurface);
d->renderControl->initialize(d->context);
d->context->doneCurrent();
}
FboQuickWindow::~FboQuickWindow()
{
delete d_ptr;
}
QImage FboQuickWindow::grab() const
{
Q_D(const FboQuickWindow);
return d->renderControl->grab();
}
void FboQuickWindow::resize(const QSize &newSize)
{
QResizeEvent event(size(), newSize);
setGeometry(0, 0, newSize.width(), newSize.height());
resizeEvent(&event);
}
void FboQuickWindow::resize(int w, int h)
{
resize(QSize(w, h));
}
void FboQuickWindow::resizeEvent(QResizeEvent *event)
{
Q_D(FboQuickWindow);
QQuickWindow::resizeEvent(event);
Q_ASSERT(d->context);
if (d->context->makeCurrent(d->offscreenSurface)) {
d->sceneGraphInvalidated();
d->sceneGraphInitialized();
d->context->doneCurrent();
}
}
#include "fboquickwindow.moc"
Any thoughts or inputs is very helpful, many thanks.