tst_qquickwindow: Add basic rendererInterface test
And remove some dead code. Change-Id: Ic49acb1241020dea4ebff829d335d3b98716bbc0 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
6ca0145f06
commit
fdba8facd0
|
@ -45,8 +45,12 @@
|
||||||
#include <private/qquickwindow_p.h>
|
#include <private/qquickwindow_p.h>
|
||||||
#include <private/qguiapplication_p.h>
|
#include <private/qguiapplication_p.h>
|
||||||
#include <QRunnable>
|
#include <QRunnable>
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
#include <QSGRendererInterface>
|
#include <QSGRendererInterface>
|
||||||
|
#include <QQuickRenderControl>
|
||||||
|
#include <functional>
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#include <QOpenGLContext>
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
|
Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests")
|
||||||
|
|
||||||
|
@ -485,6 +489,8 @@ private slots:
|
||||||
void testShortCut();
|
void testShortCut();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void rendererInterface();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTouchDevice *touchDevice;
|
QTouchDevice *touchDevice;
|
||||||
QTouchDevice *touchDeviceWithVelocity;
|
QTouchDevice *touchDeviceWithVelocity;
|
||||||
|
@ -2493,29 +2499,6 @@ public:
|
||||||
}
|
}
|
||||||
static int deleted;
|
static int deleted;
|
||||||
};
|
};
|
||||||
#if QT_CONFIG(opengl)
|
|
||||||
class GlRenderJob : public QRunnable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GlRenderJob(GLubyte *buf) : readPixel(buf), mutex(nullptr), condition(nullptr) {}
|
|
||||||
~GlRenderJob() {}
|
|
||||||
void run() {
|
|
||||||
QOpenGLContext::currentContext()->functions()->glClearColor(1.0f, 0, 0, 1.0f);
|
|
||||||
QOpenGLContext::currentContext()->functions()->glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
QOpenGLContext::currentContext()->functions()->glReadPixels(0, 0, 1, 1, GL_RGBA,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
(void *)readPixel);
|
|
||||||
if (mutex) {
|
|
||||||
mutex->lock();
|
|
||||||
condition->wakeOne();
|
|
||||||
mutex->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GLubyte *readPixel;
|
|
||||||
QMutex *mutex;
|
|
||||||
QWaitCondition *condition;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
int RenderJob::deleted = 0;
|
int RenderJob::deleted = 0;
|
||||||
|
|
||||||
void tst_qquickwindow::testRenderJob()
|
void tst_qquickwindow::testRenderJob()
|
||||||
|
@ -2563,33 +2546,6 @@ void tst_qquickwindow::testRenderJob()
|
||||||
QQuickWindow::NoStage);
|
QQuickWindow::NoStage);
|
||||||
QTRY_COMPARE(RenderJob::deleted, 1);
|
QTRY_COMPARE(RenderJob::deleted, 1);
|
||||||
QCOMPARE(completedJobs.size(), 1);
|
QCOMPARE(completedJobs.size(), 1);
|
||||||
|
|
||||||
#if QT_CONFIG(opengl)
|
|
||||||
if (window.rendererInterface()->graphicsApi() == QSGRendererInterface::OpenGL) {
|
|
||||||
// Do a synchronized GL job.
|
|
||||||
GLubyte readPixel[4] = {0, 0, 0, 0};
|
|
||||||
GlRenderJob *glJob = new GlRenderJob(readPixel);
|
|
||||||
QOpenGLContext *ctx = static_cast<QOpenGLContext *>(window.rendererInterface()->getResource(
|
|
||||||
&window, QSGRendererInterface::OpenGLContextResource));
|
|
||||||
QVERIFY(ctx);
|
|
||||||
if (ctx->thread() != QThread::currentThread()) {
|
|
||||||
QMutex mutex;
|
|
||||||
QWaitCondition condition;
|
|
||||||
glJob->mutex = &mutex;
|
|
||||||
glJob->condition = &condition;
|
|
||||||
mutex.lock();
|
|
||||||
window.scheduleRenderJob(glJob, QQuickWindow::NoStage);
|
|
||||||
condition.wait(&mutex);
|
|
||||||
mutex.unlock();
|
|
||||||
} else {
|
|
||||||
window.scheduleRenderJob(glJob, QQuickWindow::NoStage);
|
|
||||||
}
|
|
||||||
QCOMPARE(int(readPixel[0]), 255);
|
|
||||||
QCOMPARE(int(readPixel[1]), 0);
|
|
||||||
QCOMPARE(int(readPixel[2]), 0);
|
|
||||||
QCOMPARE(int(readPixel[3]), 255);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that jobs are deleted when window is not rendered at all
|
// Verify that jobs are deleted when window is not rendered at all
|
||||||
|
@ -3636,6 +3592,109 @@ void tst_qquickwindow::testShortCut()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void tst_qquickwindow::rendererInterface()
|
||||||
|
{
|
||||||
|
QQmlEngine engine;
|
||||||
|
QQmlComponent component(&engine);
|
||||||
|
component.loadUrl(testFileUrl("Headless.qml"));
|
||||||
|
QObject *created = component.create();
|
||||||
|
QScopedPointer<QObject> cleanup(created);
|
||||||
|
|
||||||
|
QQuickWindow *window = qobject_cast<QQuickWindow*>(created);
|
||||||
|
QVERIFY(window);
|
||||||
|
window->setTitle(QTest::currentTestFunction());
|
||||||
|
window->show();
|
||||||
|
|
||||||
|
QVERIFY(QTest::qWaitForWindowExposed(window));
|
||||||
|
QVERIFY(window->isSceneGraphInitialized());
|
||||||
|
QVERIFY(window->rendererInterface());
|
||||||
|
|
||||||
|
QSGRendererInterface *rif = window->rendererInterface();
|
||||||
|
QVERIFY(rif->graphicsApi() != QSGRendererInterface::Unknown);
|
||||||
|
|
||||||
|
// Verify the essential integration points used by Quick3D.
|
||||||
|
if (QSGRendererInterface::isApiRhiBased(rif->graphicsApi())) {
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::RhiResource));
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::RhiSwapchainResource));
|
||||||
|
// the rendercontrol specific objects should not be present for an on-screen window
|
||||||
|
QVERIFY(!rif->getResource(window, QSGRendererInterface::RhiRedirectCommandBuffer));
|
||||||
|
QVERIFY(!rif->getResource(window, QSGRendererInterface::RhiRedirectRenderTarget));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, depending on the graphics API, verify the native objects that are
|
||||||
|
// most common in applications that integrate native rendering code. Check
|
||||||
|
// only the globally available ones (that are available whenever the
|
||||||
|
// scenegraph is initialized, not just during recording a frame)
|
||||||
|
switch (rif->graphicsApi()) {
|
||||||
|
case QSGRendererInterface::OpenGLRhi:
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::OpenGLContextResource));
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
{
|
||||||
|
QOpenGLContext *ctx = static_cast<QOpenGLContext *>(rif->getResource(window, QSGRendererInterface::OpenGLContextResource));
|
||||||
|
QVERIFY(ctx->isValid());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case QSGRendererInterface::Direct3D11Rhi:
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::DeviceResource));
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::DeviceContextResource));
|
||||||
|
break;
|
||||||
|
case QSGRendererInterface::VulkanRhi:
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::DeviceResource));
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::PhysicalDeviceResource));
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::VulkanInstanceResource));
|
||||||
|
#if QT_CONFIG(vulkan)
|
||||||
|
QCOMPARE(rif->getResource(window, QSGRendererInterface::VulkanInstanceResource), window->vulkanInstance());
|
||||||
|
#endif
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::CommandQueueResource));
|
||||||
|
break;
|
||||||
|
case QSGRendererInterface::MetalRhi:
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::DeviceResource));
|
||||||
|
QVERIFY(rif->getResource(window, QSGRendererInterface::CommandQueueResource));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now the objects that are available only when preparing a frame.
|
||||||
|
if (QSGRendererInterface::isApiRhiBased(rif->graphicsApi())) {
|
||||||
|
bool ok[4] = { false, false, false, false };
|
||||||
|
auto f = [&ok, window](int idx) {
|
||||||
|
QSGRendererInterface *rif = window->rendererInterface();
|
||||||
|
if (rif) {
|
||||||
|
ok[idx] = true;
|
||||||
|
switch (rif->graphicsApi()) {
|
||||||
|
case QSGRendererInterface::VulkanRhi:
|
||||||
|
if (!rif->getResource(window, QSGRendererInterface::CommandListResource))
|
||||||
|
ok[idx] = false;
|
||||||
|
if (!rif->getResource(window, QSGRendererInterface::RenderPassResource))
|
||||||
|
ok[idx] = false;
|
||||||
|
break;
|
||||||
|
case QSGRendererInterface::MetalRhi:
|
||||||
|
if (!rif->getResource(window, QSGRendererInterface::CommandListResource))
|
||||||
|
ok[idx] = false;
|
||||||
|
if (!rif->getResource(window, QSGRendererInterface::CommandEncoderResource))
|
||||||
|
ok[idx] = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Also tests if all 4 signals are emitted as expected.
|
||||||
|
QObject::connect(window, &QQuickWindow::beforeRendering, window, std::bind(f, 0), Qt::DirectConnection);
|
||||||
|
QObject::connect(window, &QQuickWindow::beforeRenderPassRecording, window, std::bind(f, 1), Qt::DirectConnection);
|
||||||
|
QObject::connect(window, &QQuickWindow::afterRenderPassRecording, window, std::bind(f, 2), Qt::DirectConnection);
|
||||||
|
QObject::connect(window, &QQuickWindow::afterRendering, window, std::bind(f, 3), Qt::DirectConnection);
|
||||||
|
window->grabWindow();
|
||||||
|
QVERIFY(ok[0]);
|
||||||
|
QVERIFY(ok[1]);
|
||||||
|
QVERIFY(ok[2]);
|
||||||
|
QVERIFY(ok[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_qquickwindow)
|
QTEST_MAIN(tst_qquickwindow)
|
||||||
|
|
||||||
#include "tst_qquickwindow.moc"
|
#include "tst_qquickwindow.moc"
|
||||||
|
|
Loading…
Reference in New Issue