summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaj Grönholm <kaj.gronholm@qt.io>2019-06-10 12:26:17 +0300
committerKaj Grönholm <kaj.gronholm@qt.io>2019-06-11 12:50:49 +0300
commit0cd2ed2fc3cadc0d14df16cbd2653772437ce4ac (patch)
tree7e27d3d9aa226e785f362c0a811f374c965206fd
parenta06fe056604b38d52ebca44d52b87f736b483649 (diff)
Move autotests into ogl-runtime repository
Move all autotests into ogl-runtime as they are testing runtime and not qt3dstudio. Adjust to build on new structure, but keep tests disabled by default until making sure CI can build & run them. Task-number: QT3DS-3627 Change-Id: I8abb87424ee5d89d05017235cdf15bd6c0f6d490 Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io> Reviewed-by: Antti Määttä <antti.maatta@qt.io> Reviewed-by: Pasi Keränen <pasi.keranen@qt.io>
-rw-r--r--testres.qrc14
-rw-r--r--tests/auto/auto.pro10
-rw-r--r--tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro18
-rw-r--r--tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp106
-rw-r--r--tests/auto/qtextras/qtextras.pro4
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestBase.cpp101
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestBase.h164
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp118
-rw-r--r--tests/auto/runtime/Qt3DSRenderTestMathUtil.h50
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp248
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h59
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp251
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h59
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp332
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h62
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestClear.cpp131
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestClear.h56
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp847
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h63
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp358
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h60
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp321
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h77
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp401
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h60
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp288
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h67
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp436
-rw-r--r--tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h64
-rw-r--r--tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp636
-rw-r--r--tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h61
-rw-r--r--tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp299
-rw-r--r--tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h67
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp390
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h60
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp367
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h66
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp560
-rw-r--r--tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h60
-rw-r--r--tests/auto/runtime/images/NVRenderTestAttribBuffers.pngbin0 -> 3820 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestBackendQuery.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestClear.pngbin0 -> 2327 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestComputeShader.pngbin0 -> 3889 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestFboMsaa.pngbin0 -> 3168 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestGeometryShader.pngbin0 -> 3311 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestOcclusionQuery.pngbin0 -> 2355 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestProgramPipeline.pngbin0 -> 3224 bytes
-rw-r--r--tests/auto/runtime/images/NVRenderTestTexture2D.pngbin0 -> 2991 bytes
-rw-r--r--tests/auto/runtime/runtime.pro82
-rw-r--r--tests/auto/runtime/runtime.qrc14
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp469
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h55
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp574
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h56
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp155
-rw-r--r--tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h55
-rw-r--r--tests/auto/runtime/tst_qt3dsruntime.cpp727
-rw-r--r--tests/auto/runtime/tst_qt3dsruntime.h144
-rw-r--r--tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro10
-rw-r--r--tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp1516
-rw-r--r--tests/auto/studio3d/shared/presentation/animation.uip35
-rw-r--r--tests/auto/studio3d/shared/presentation/blue.uip31
-rw-r--r--tests/auto/studio3d/shared/presentation/datainput.uia18
-rw-r--r--tests/auto/studio3d/shared/presentation/datainput.uip63
-rw-r--r--tests/auto/studio3d/shared/presentation/datainput_sub.uip31
-rw-r--r--tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttfbin0 -> 63752 bytes
-rw-r--r--tests/auto/studio3d/shared/presentation/mixed.uip36
-rw-r--r--tests/auto/studio3d/shared/presentation/mixed_vertical.uip36
-rw-r--r--tests/auto/studio3d/shared/presentation/mouse.uip54
-rw-r--r--tests/auto/studio3d/shared/presentation/multislide.uip99
-rw-r--r--tests/auto/studio3d/shared/presentation/red.uip31
-rw-r--r--tests/auto/studio3d/shared/presentation/settings.uip31
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.h39
-rw-r--r--tests/auto/studio3d/shared/shared_presentations.qrc15
-rw-r--r--tests/auto/studio3d/studio3d.pro4
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.cpp762
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.h80
-rw-r--r--tests/auto/viewer/tst_qt3dsviewer.qml62
-rw-r--r--tests/auto/viewer/viewer.pro21
-rw-r--r--tests/auto/viewer/viewer.qrc16
-rw-r--r--tests/scenes/customvertex/customvertex.uia15
-rw-r--r--tests/scenes/customvertex/materials/simple.shader29
-rw-r--r--tests/scenes/customvertex/presentations/customvertex.uip33
-rw-r--r--tests/scenes/simple_cube_animation/maps/QT-symbol.pngbin0 -> 4541 bytes
-rw-r--r--tests/scenes/simple_cube_animation/maps/materials/shadow.pngbin0 -> 334 bytes
-rw-r--r--tests/scenes/simple_cube_animation/maps/materials/spherical_checker.pngbin0 -> 11066 bytes
-rw-r--r--tests/scenes/simple_cube_animation/materials/Basic Blue.materialdef25
-rw-r--r--tests/scenes/simple_cube_animation/materials/Basic Green.materialdef25
-rw-r--r--tests/scenes/simple_cube_animation/materials/Basic Red.materialdef25
-rw-r--r--tests/scenes/simple_cube_animation/materials/Basic Texture.materialdef63
-rw-r--r--tests/scenes/simple_cube_animation/materials/Copper.materialdef14
-rw-r--r--tests/scenes/simple_cube_animation/materials/copper.shader178
-rw-r--r--tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip62
-rw-r--r--tests/scenes/simple_cube_animation/simple_cube_animation.uia16
-rw-r--r--tests/tests.pro3
96 files changed, 13186 insertions, 14 deletions
diff --git a/testres.qrc b/testres.qrc
deleted file mode 100644
index 79643b8..0000000
--- a/testres.qrc
+++ /dev/null
@@ -1,14 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file alias="aluminium.shader">Content/Material Library/aluminum.shader</file>
- <file alias="asphalt.shader">Content/Material Library/asphalt.shader</file>
- <file alias="concrete.shader">Content/Material Library/concrete.shader</file>
- <file alias="copper.shader">Content/Material Library/copper.shader</file>
- <file alias="porcelain.shader">Content/Material Library/porcelain.shader</file>
- <file alias="simple_glass.shader">Content/Material Library/simple_glass.shader</file>
- <file alias="Desaturate.effect">Content/Effect Library/Desaturate.effect</file>
- <file alias="Gaussian Blur.effect">Content/Effect Library/Gaussian Blur.effect</file>
- <file alias="Sepia.effect">Content/Effect Library/Sepia.effect</file>
- <file alias="Bloom.effect">Content/Effect Library/Bloom.effect</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
new file mode 100644
index 0000000..2f410f5
--- /dev/null
+++ b/tests/auto/auto.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+CONFIG += ordered
+
+!macos:!win32: SUBDIRS += \
+ qtextras
+
+# TODO: Re-enable these tests after confirming CI can build & run them
+# runtime \
+# viewer \
+# studio3d
diff --git a/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro b/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro
new file mode 100644
index 0000000..57aab92
--- /dev/null
+++ b/tests/auto/qtextras/qt3dsqmlstream/qt3dsqmlstream.pro
@@ -0,0 +1,18 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../../commonplatform.pri)
+
+TARGET = tst_qt3dsqmlstream
+
+QT += testlib quick
+
+SOURCES += tst_qt3dsqmlstream.cpp
+
+INCLUDEPATH += \
+ $$PWD/../../../../src/qmlstreamer
+
+LIBS += \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsqmlstreamer.so
diff --git a/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp b/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp
new file mode 100644
index 0000000..71de525
--- /dev/null
+++ b/tests/auto/qtextras/qt3dsqmlstream/tst_qt3dsqmlstream.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QSignalSpy>
+#include <q3dsqmlstream.h>
+#include <QQuickItem>
+
+class tst_Qt3DSQmlStream : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Qt3DSQmlStream()
+ {
+ qRegisterMetaType<QQuickItem*>();
+ }
+ ~tst_Qt3DSQmlStream() {}
+private slots:
+
+ void checkInitialState()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+
+ // THEN
+ QVERIFY(qmlstream.presentationId().isNull());
+ QVERIFY(qmlstream.item() == nullptr);
+ }
+
+ void testSetPresentationId()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+ QString pid = "presentation0";
+ QSignalSpy spy(&qmlstream, SIGNAL(presentationIdChanged(const QString&)));
+
+ // WHEN
+ qmlstream.setPresentationId(pid);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(qmlstream.presentationId(), pid);
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ qmlstream.setPresentationId(pid);
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+ }
+
+ void testSetItem()
+ {
+ // GIVEN
+ Q3DSQmlStream qmlstream;
+ QScopedPointer<QQuickItem> item(new QQuickItem());
+ QSignalSpy spy(&qmlstream, SIGNAL(itemChanged(QQuickItem *)));
+
+ // WHEN
+ qmlstream.setItem(item.data());
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(qmlstream.item(), item.data());
+ QCOMPARE(spy.count(), 1);
+
+ // WHEN
+ spy.clear();
+ qmlstream.setItem(item.data());
+
+ // THEN
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+ }
+};
+
+QTEST_APPLESS_MAIN(tst_Qt3DSQmlStream)
+
+#include "tst_qt3dsqmlstream.moc"
diff --git a/tests/auto/qtextras/qtextras.pro b/tests/auto/qtextras/qtextras.pro
new file mode 100644
index 0000000..16a1ed8
--- /dev/null
+++ b/tests/auto/qtextras/qtextras.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ qt3dsqmlstream
diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.cpp b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
new file mode 100644
index 0000000..f4ab079
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestBase.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestBase.h"
+
+#include "Qt3DSDMPrefix.h"
+#include "EASTL/allocator.h"
+
+namespace eastl
+{
+void AssertionFailure(const char* pExpression)
+{
+ Q_UNUSED(pExpression);
+}
+EmptyString gEmptyString;
+void* gpEmptyBucketArray[2] = { nullptr, (void*)uintptr_t(~0) };
+}
+
+namespace qt3ds {
+
+void Qt3DSAssert(const char *exp, const char *file, int line, bool *ignore)
+{
+ Q_UNUSED(ignore)
+ qFatal("Assertion thrown %s(%d): %s", file, line, exp);
+}
+
+namespace render {
+SEndlType Endl;
+}
+}
+
+void *operator new[](size_t size, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+
+void *operator new[](size_t size, size_t, size_t, const char *, int, unsigned, const char *, int)
+{
+ return malloc(size);
+}
+
+using namespace qt3ds::render;
+
+namespace qt3ds {
+namespace render {
+
+NVRenderTestBase::~NVRenderTestBase()
+{
+ delete m_renderImpl;
+}
+
+bool NVRenderTestBase::initializeQt3DSRenderer(QSurfaceFormat format)
+{
+ m_coreFactory = qt3ds::render::IQt3DSRenderFactoryCore::CreateRenderFactoryCore("", m_windowSystem,
+ m_timeProvider);
+ m_factory = m_coreFactory->CreateRenderFactory(format, false);
+ m_rc = m_factory->GetQt3DSRenderContext();
+ m_renderImpl = new qt3ds::render::Qt3DSRendererImpl(*m_rc);
+
+ return true;
+}
+
+Qt3DSRendererImpl *NVRenderTestBase::qt3dsRenderer()
+{
+ return m_renderImpl;
+}
+
+Q3DStudio::IRuntimeMetaData *NVRenderTestBase::metadata()
+{
+ if (m_metaData.mPtr == NULL)
+ m_metaData = &Q3DStudio::IRuntimeMetaData::Create(m_coreFactory->GetInputStreamFactory());
+ return m_metaData.mPtr;
+}
+
+}
+}
diff --git a/tests/auto/runtime/Qt3DSRenderTestBase.h b/tests/auto/runtime/Qt3DSRenderTestBase.h
new file mode 100644
index 0000000..bde0948
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestBase.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_BASE_H
+#define QT3DS_RENDER_TEST_BASE_H
+#include "foundation/Qt3DS.h"
+#include "foundation/Qt3DSAssert.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "render/Qt3DSRenderBaseTypes.h"
+#include "render/Qt3DSRenderContext.h"
+#include "Qt3DSWindowSystem.h"
+#include "Qt3DSTypes.h"
+#include "Qt3DSTimer.h"
+#include "Qt3DSRenderRuntimeBinding.h"
+#include "Qt3DSRenderRuntimeBindingImpl.h"
+#include "Qt3DSRenderContextCore.h"
+#include "rendererimpl/Qt3DSRendererImpl.h"
+#include "Qt3DSMetadata.h"
+
+namespace qt3ds {
+namespace render {
+class IQt3DSRenderer;
+class Qt3DSRendererImpl;
+class IQt3DSRenderFactoryCore;
+class IQt3DSRenderFactory;
+}
+}
+
+namespace qt3ds {
+namespace render {
+
+ class IQt3DSRenderFactoryCore;
+ class IQt3DSRenderFactory;
+ class Qt3DSRenderer;
+
+ typedef struct SUSER_CONTEXT_DATA
+ {
+ unsigned int winWidth;
+ unsigned int winHeight;
+ } userContextData;
+
+ struct SNullTimeProvider : public Q3DStudio::ITimeProvider
+ {
+ virtual Q3DStudio::INT64 GetCurrentTimeMicroSeconds() { return 0; }
+ };
+
+ struct SNullWindowSystem : public Q3DStudio::IWindowSystem
+ {
+ virtual QSize GetWindowDimensions() { return QSize(); }
+
+ virtual void SetWindowDimensions(const QSize &) {}
+ // For platforms that support it, we get the egl info for render plugins
+ // Feel free to return NULL.
+ virtual Q3DStudio::SEGLInfo *GetEGLInfo() { return NULL; }
+
+ // on some systems we allow our default render target to be a offscreen buffer
+ // otherwise return 0;
+ virtual int GetDefaultRenderTargetID() { return 0; }
+ // returns the depth buffer bit count for the render window
+ // does not really matter here
+ virtual int GetDepthBitCount() { return 16; }
+ };
+
+ /// this is the base class for all tests
+ class NVRenderTestBase
+ {
+ public:
+ /// constructor
+ NVRenderTestBase(){}
+ /// destructor
+ virtual ~NVRenderTestBase();
+
+ /// Checks if this test is supported
+ ///
+ /// @return true if supported
+ virtual bool isSupported(NVRenderContext *context) = 0;
+
+ /// This runs the test
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual bool run(NVRenderContext *context, userContextData *pUserData) = 0;
+
+ /// This cleans up state after the test if needed
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual void cleanup(NVRenderContext *context, userContextData *pUserData) = 0;
+
+ /// This runs the performance test
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ /// @param pUserData (in) Pointer to pUserData
+ ///
+ /// @return false if failed
+ virtual bool runPerformance(NVRenderContext *context, userContextData *pContextData) = 0;
+
+ /// This is a query to determine if we run on a ES context
+ ///
+ /// @param context (in) Pointer to a NVRenderContext context
+ ///
+ /// @return false if failed
+ virtual const bool isGLESContext(NVRenderContext *context)
+ {
+ NVRenderContextType ctxType = context->GetRenderContextType();
+
+ // Need minimum of GL3 or GLES3
+ if (ctxType == NVRenderContextValues::GLES2 || ctxType == NVRenderContextValues::GLES3
+ || ctxType == NVRenderContextValues::GLES3PLUS) {
+ return true;
+ }
+
+ return false;
+ }
+
+ bool initializeQt3DSRenderer(QSurfaceFormat format);
+ qt3ds::render::Qt3DSRendererImpl *qt3dsRenderer();
+ Q3DStudio::IRuntimeMetaData *metadata();
+
+ private:
+
+ NVScopedRefCounted<qt3ds::render::IQt3DSRenderFactoryCore> m_coreFactory;
+ NVScopedRefCounted<qt3ds::render::IQt3DSRenderFactory> m_factory;
+ NVScopedRefCounted<qt3ds::render::IQt3DSRenderContext> m_rc;
+ qt3ds::foundation::NVScopedReleasable<Q3DStudio::IRuntimeMetaData> m_metaData;
+ qt3ds::render::Qt3DSRendererImpl *m_renderImpl;
+
+ SNullTimeProvider m_timeProvider;
+ SNullWindowSystem m_windowSystem;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_BASE_H
diff --git a/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp b/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp
new file mode 100644
index 0000000..f216faa
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestMathUtil.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestMathUtil.h"
+#include <math.h>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+#define QT3DS_RENDER_TEST_PI 3.14159265358979323846f
+
+inline float degreeToRad(float degree)
+{
+ return (degree * QT3DS_RENDER_TEST_PI) / 180.0f;
+}
+
+void qt3ds::render::NvRenderTestMatrixFrustum(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f)
+{
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv, twoNear;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+ twoNear = 2.0f * n;
+
+ m->column0 = QT3DSVec4(twoNear * rightMinusLeftInv, 0, 0, 0);
+ m->column1 = QT3DSVec4(0, twoNear * topMinusBottomInv, 0, 0);
+ m->column2 = QT3DSVec4((r + l) * rightMinusLeftInv, (t + b) * topMinusBottomInv,
+ -(f + n) * farMinusNearInv, -1.0f);
+ m->column3 = QT3DSVec4(0, 0, -(twoNear * f) * farMinusNearInv, 0.0f);
+}
+
+void qt3ds::render::NvGl2DemoMatrixOrtho(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f)
+{
+ float rightMinusLeftInv, topMinusBottomInv, farMinusNearInv;
+
+ rightMinusLeftInv = 1.0f / (r - l);
+ topMinusBottomInv = 1.0f / (t - b);
+ farMinusNearInv = 1.0f / (f - n);
+
+ m->column0 = QT3DSVec4(2.0f * rightMinusLeftInv, 0, 0, 0);
+ m->column1 = QT3DSVec4(0, 2.0f * topMinusBottomInv, 0, 0);
+ m->column2 = QT3DSVec4(0, 0, -2.0f * farMinusNearInv, 0);
+ m->column3 = QT3DSVec4(-(r + l) * rightMinusLeftInv, -(t + b) * topMinusBottomInv,
+ -(f + n) * farMinusNearInv, 1.0f);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotX(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(1.0, 0.0, 0.0, 0.0);
+ m->column1 = QT3DSVec4(0.0, cosPhi, -sinPhi, 0.0);
+ m->column2 = QT3DSVec4(0.0, sinPhi, cosPhi, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotY(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(cosPhi, 0.0, sinPhi, 0.0);
+ m->column1 = QT3DSVec4(0.0, 1.0, 0.0, 0.0);
+ m->column2 = QT3DSVec4(-sinPhi, 0.0, cosPhi, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixRotZ(QT3DSMat44 *m, float angle)
+{
+ float rad = degreeToRad(angle);
+ float cosPhi = cos(rad);
+ float sinPhi = sin(rad);
+
+ m->column0 = QT3DSVec4(cosPhi, -sinPhi, 0.0, 0.0);
+ m->column1 = QT3DSVec4(sinPhi, cosPhi, 0.0, 0.0);
+ m->column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ m->column3 = QT3DSVec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void qt3ds::render::NvRenderTestMatrixTranslation(QT3DSMat44 *m, float x, float y, float z)
+{
+ m->column0 = QT3DSVec4(1.0, 0.0, 0.0, 0.0);
+ m->column1 = QT3DSVec4(0.0, 1.0, 0.0, 0.0);
+ m->column2 = QT3DSVec4(0.0, 0.0, 1.0, 0.0);
+ m->column3 = QT3DSVec4(x, y, z, 1.0);
+}
diff --git a/tests/auto/runtime/Qt3DSRenderTestMathUtil.h b/tests/auto/runtime/Qt3DSRenderTestMathUtil.h
new file mode 100644
index 0000000..739209e
--- /dev/null
+++ b/tests/auto/runtime/Qt3DSRenderTestMathUtil.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_MATH_UTIL_H
+#define QT3DS_RENDER_TEST_MATH_UTIL_H
+
+#include "foundation/Qt3DSMat44.h"
+
+namespace qt3ds {
+namespace render {
+
+ void NvRenderTestMatrixFrustum(QT3DSMat44 *m, float l, float r, float b, float t, float n,
+ float f);
+
+ void NvGl2DemoMatrixOrtho(QT3DSMat44 *m, float l, float r, float b, float t, float n, float f);
+
+ void NvRenderTestMatrixRotX(QT3DSMat44 *m, float angle);
+ void NvRenderTestMatrixRotY(QT3DSMat44 *m, float angle);
+ void NvRenderTestMatrixRotZ(QT3DSMat44 *m, float angle);
+
+ void NvRenderTestMatrixTranslation(QT3DSMat44 *m, float x, float y, float z);
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp
new file mode 100644
index 0000000..9f81214
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestAtomicCounterBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderAtomicCounterBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "layout(binding = 2, offset = 0) uniform atomic_uint ac_raster;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " uint counter = atomicCounterIncrement(ac_raster);\n"
+ " float g = (float(counter)/255.0) / 255.0;\n"
+ " fragColor = vec4(0.0, g, 0.0, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestAtomicCounterBuffer::NVRenderTestAtomicCounterBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestAtomicCounterBuffer::~NVRenderTestAtomicCounterBuffer()
+{
+}
+
+bool NVRenderTestAtomicCounterBuffer::isSupported(NVRenderContext *context)
+{
+ // This is currently only supported on GL 4 and GLES 3.1
+ if (!context->IsAtomicCounterBufferSupported())
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestAtomicCounterBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= rasterizerTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestAtomicCounterBuffer::rasterizerTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderAtomicCounterBuffer> mAtomicCounterBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create atomic counter buffer
+ QT3DSU32 acCounter = 0;
+ NVDataRef<QT3DSU8> acData((QT3DSU8 *)&acCounter, sizeof(QT3DSU32));
+ mAtomicCounterBuffer = context->CreateAtomicCounterBuffer(
+ "ac_buffer", NVRenderBufferUsageType::Static, sizeof(QT3DSU32), acData);
+ if (!mAtomicCounterBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create atomic counter buffer";
+ return false;
+ }
+ // add a parameter
+ CRegisteredString theACName(context->GetStringTable().RegisterStr("ac_raster"));
+ mAtomicCounterBuffer->AddParam(theACName, 0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestAtomicCounterBuffer shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderAtomicCounterBuffer *> atomicBuffer(
+ "ac_buffer", *compResult.mShader);
+ atomicBuffer.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestAtomicCounterBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestAtomicCounterBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h
new file mode 100644
index 0000000..87b0910
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAtomicCounterBuffer.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
+#define QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestAtomicCounterBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestAtomicCounterBuffer();
+ ~NVRenderTestAtomicCounterBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool rasterizerTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp
new file mode 100644
index 0000000..805782f
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestAttribBuffers.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_col; // Vertex col\n"
+ "out vec3 color; // output color\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ " color = attr_col;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "in vec3 color; // input color\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4( color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestAttribBuffers::NVRenderTestAttribBuffers()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestAttribBuffers::~NVRenderTestAttribBuffers()
+{
+}
+
+bool NVRenderTestAttribBuffers::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestAttribBuffers::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= multiAttribBufferTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestAttribBuffers::multiAttribBufferTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 0.6, 0.0) },
+ { QT3DSVec3(0.0, 0.2, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestAttribBuffers shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestAttribBuffers::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestAttribBuffers::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h
new file mode 100644
index 0000000..47e898f
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestAttribBuffers.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
+#define QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestAttribBuffers : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestAttribBuffers();
+ ~NVRenderTestAttribBuffers();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool multiAttribBufferTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATTRIB_BUFFERS_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp
new file mode 100644
index 0000000..30f2637
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.cpp
@@ -0,0 +1,332 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestBackendQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform vec3 color;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4( color, 1);\n"
+ "}\n";
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+NVRenderTestBackendQuery::NVRenderTestBackendQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestBackendQuery::~NVRenderTestBackendQuery()
+{
+}
+
+bool NVRenderTestBackendQuery::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestBackendQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= depthBitsTest(context, pUserData);
+ _curTest++;
+ success &= depthBitsFBOTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestBackendQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestBackendQuery shader", toRef(PassthroughVertShader()),
+ toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsTest: Failed to create input assembler";
+ return false;
+ }
+
+ // check if default buffer bit size is in an acceptable size range
+ // we accept a range from 16 to 32
+ const QT3DSU32 bits = context->GetDepthBits();
+ bool passed = (bits >= 16 && bits <= 32);
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return passed;
+}
+
+bool NVRenderTestBackendQuery::depthBitsTest(NVRenderContext *context, userContextData *pUserData)
+{
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ // check if default buffer bit size is in an acceptable size range
+ // we accept a range from 16 to 32
+ const QT3DSU32 bits = context->GetDepthBits();
+ bool passed = (bits >= 16 && bits <= 32);
+ if (passed)
+ color.y = 1.0;
+ else
+ color.x = 1.0;
+
+ passed &= renderQuad(context, pUserData, color);
+
+ return passed;
+}
+
+bool NVRenderTestBackendQuery::depthBitsFBOTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ // depneding on the context we get different values
+ NVRenderContextType theContextFlags(NVRenderContextValues::GLES2 | NVRenderContextValues::GL2);
+ NVRenderContextType type = context->GetRenderContextType();
+ bool depth16_Only = (type & theContextFlags);
+ // create a FBO
+ NVScopedRefCounted<NVRenderFrameBuffer> m_FBO;
+ NVScopedRefCounted<NVRenderTexture2D> m_ColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth16Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth24Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth32Texture;
+ NVScopedRefCounted<NVRenderTexture2D> m_Depth24Stencil8Texture;
+
+ m_ColorTexture = context->CreateTexture2D();
+ m_ColorTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256, NVRenderTextureFormats::RGBA8);
+ m_Depth16Texture = context->CreateTexture2D();
+ m_Depth16Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth16);
+
+ m_FBO = context->CreateFrameBuffer();
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*m_ColorTexture));
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth16Texture));
+
+ if (!m_FBO->IsComplete()) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+
+ context->SetRenderTarget(m_FBO);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ // check depth bit count
+ QT3DSU32 bits = context->GetDepthBits();
+ QT3DSU32 bitsExpected = 16;
+ bool passed = (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ m_Depth24Texture = context->CreateTexture2D();
+ m_Depth24Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth24);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth24Texture));
+ if (!m_FBO->IsComplete()) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 24;
+ passed &= (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ m_Depth32Texture = context->CreateTexture2D();
+ m_Depth32Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth32);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_Depth32Texture));
+ if (!m_FBO->IsComplete()) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 32;
+ passed &= (bits == bitsExpected);
+
+ // detach depth
+ m_FBO->Attach(NVRenderFrameBufferAttachments::Depth, NVRenderTextureOrRenderBuffer());
+
+ // only test depth stencil if supported
+ if (context->IsDepthStencilSupported()) {
+ m_Depth24Stencil8Texture = context->CreateTexture2D();
+ m_Depth24Stencil8Texture->SetTextureData(NVDataRef<QT3DSU8>(), 0, 256, 256,
+ NVRenderTextureFormats::Depth24Stencil8);
+ m_FBO->Attach(NVRenderFrameBufferAttachments::DepthStencil,
+ NVRenderTextureOrRenderBuffer(*m_Depth24Stencil8Texture));
+ if (!m_FBO->IsComplete()) {
+ qWarning() << "NVRenderTestBackendQuery::depthBitsFBOTest: Failed to create FBO";
+ return false;
+ }
+ // check depth bit count
+ bits = context->GetDepthBits();
+ bitsExpected = (depth16_Only) ? 16 : 24;
+ passed &= (bits == bitsExpected);
+ }
+
+ context->SetRenderTarget(NULL);
+
+ if (passed)
+ color.y = 1.0;
+ else
+ color.x = 1.0;
+
+ passed &= renderQuad(context, pUserData, color);
+
+ return passed;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestBackendQuery::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestBackendQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h
new file mode 100644
index 0000000..e5fde64
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestBackendQuery.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_BACKEND_QUERY_H
+#define QT3DS_RENDER_TEST_BACKEND_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestBackendQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestBackendQuery();
+ ~NVRenderTestBackendQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool depthBitsTest(NVRenderContext *context, userContextData *pUserData);
+ bool depthBitsFBOTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp b/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp
new file mode 100644
index 0000000..3e80d40
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestClear.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestClear.h"
+#include "foundation/Qt3DSVec4.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+NVRenderTestClear::NVRenderTestClear()
+{
+}
+
+NVRenderTestClear::~NVRenderTestClear()
+{
+}
+
+bool NVRenderTestClear::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+static bool checkColor(int width, int height, unsigned char *pixels, const QT3DSVec3 &color)
+{
+ unsigned char *pSrc = pixels;
+
+ for (int h = 0; h < height; h++) {
+ for (int w = 0; w < width; w++) {
+ if (pSrc[0] != (unsigned char)color.x || pSrc[1] != (unsigned char)color.y
+ || pSrc[2] != (unsigned char)color.z) {
+ return false;
+ }
+
+ pSrc += 3;
+ }
+ }
+
+ return true;
+}
+
+bool NVRenderTestClear::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ success &= testColorClear(context, pUserData);
+
+ // if successful draw green otherwise a red
+ if (success) {
+ // set clear color to green
+ context->SetClearColor(QT3DSVec4(0.0f, 1.0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+ } else {
+ // set clear color to green
+ context->SetClearColor(QT3DSVec4(1.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+ }
+
+ return success;
+}
+
+bool NVRenderTestClear::testColorClear(NVRenderContext *context, userContextData *pUserData)
+{
+ // allocate buffer for readback
+ NVAllocatorCallback &alloc(context->GetFoundation().getAllocator());
+ QT3DSU32 size = pUserData->winHeight * pUserData->winHeight * 3 * sizeof(QT3DSU8);
+ QT3DSU8 *pixels = (QT3DSU8 *)alloc.allocate(size, "testColorClear color clear", __FILE__, __LINE__);
+
+ if (!pixels)
+ return false;
+
+ // set clear color to yellow
+ context->SetClearColor(QT3DSVec4(1.0f, 1.0f, .0f, 0.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color));
+
+ // read back pixels
+ context->ReadPixels(NVRenderRect(0, 0, pUserData->winHeight, pUserData->winHeight),
+ NVRenderReadPixelFormats::RGB8, NVDataRef<QT3DSU8>(pixels, size));
+ // check color
+ bool passed =
+ checkColor(pUserData->winHeight, pUserData->winHeight, pixels, QT3DSVec3(255.0f, 255.0f, .0f));
+
+ alloc.deallocate(pixels);
+
+ return passed;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestClear::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestClear::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestClear.h b/tests/auto/runtime/base/Qt3DSRenderTestClear.h
new file mode 100644
index 0000000..6113b7b
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestClear.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_CLEAR_H
+#define QT3DS_RENDER_TEST_CLEAR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the render target clearing
+ class NVRenderTestClear : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestClear();
+ ~NVRenderTestClear();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextDat);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ /// subtests
+ bool testColorClear(NVRenderContext *context, userContextData *pUserData);
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CLEAR_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp
new file mode 100644
index 0000000..8b6cb34
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestConstantBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *scalarVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "float red;\n"
+ "float green;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *scalarFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "float red;\n"
+ "float green;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(red, green, blue, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vectorVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "vec2 ba;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vectorFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBuffer { \n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "vec2 ba;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(rg[0], rg[1], ba[0], ba[1]);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *structVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "struct sampleStruct {\n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n"
+ "float alpha; };\n"
+ "layout (std140) uniform cbBuffer { \n"
+ "sampleStruct s[2]; };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = s[0].mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *structFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "struct sampleStruct {\n"
+ "vec2 rg;\n"
+ "mat4 mat_mvp;\n"
+ "float blue;\n"
+ "float alpha; };\n"
+ "layout (std140) uniform cbBuffer { \n"
+ "sampleStruct s[2]; };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(s[0].rg[0], s[0].rg[1], s[0].blue, s[0].alpha);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *multiCBVertShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBufferTrans { \n"
+ "mat4 mat_mvp;\n };\n"
+ "layout (std140) uniform cbBufferCol { \n"
+ "float red;\n"
+ "float green;\n"
+ "float blue;\n };\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *multiCBFragShader(bool bESContext, std::string &prog)
+{
+ if (bESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330 compatibility\n";
+ }
+
+ prog += "layout (std140) uniform cbBufferTrans { \n"
+ "mat4 mat_mvp;\n };\n"
+ "layout (std140) uniform cbBufferCol { \n"
+ "float red;\n"
+ "float green;\n"
+ "float blue;\n };\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(red, green, blue, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestConstantBuffer::NVRenderTestConstantBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestConstantBuffer::~NVRenderTestConstantBuffer()
+{
+}
+
+bool NVRenderTestConstantBuffer::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(NVRenderContextValues::GL2
+ | NVRenderContextValues::GLES2);
+
+ // This is currently only supported on GL(Es) >= 3
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestConstantBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= scalarTest(context, pUserData);
+ _curTest++;
+ success &= vectorTest(context, pUserData);
+ _curTest++;
+ success &= structTest(context, pUserData);
+ _curTest++;
+ success &= rawTest(context, pUserData);
+ _curTest++;
+ success &= multiCBTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestConstantBuffer::scalarTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRedName(context->GetStringTable().RegisterStr("red"));
+ mConstantBuffer->AddParam(theRedName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theGreenName(context->GetStringTable().RegisterStr("green"));
+ mConstantBuffer->AddParam(theGreenName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("blue"));
+ mConstantBuffer->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ QT3DSF32 red = 0.0;
+ mConstantBuffer->UpdateParam("red", NVDataRef<QT3DSU8>((QT3DSU8 *)&red, 1));
+ QT3DSF32 green = 1.0;
+ mConstantBuffer->UpdateParam("green", NVDataRef<QT3DSU8>((QT3DSU8 *)&green, 1));
+ QT3DSF32 blue = 0.0;
+ mConstantBuffer->UpdateParam("blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+ mConstantBuffer->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::scalarTest",
+ toRef(scalarVertShader(isGLESContext(context), vtxProg)),
+ toRef(scalarFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestConstantBuffer::scalarTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestConstantBuffer::scalarTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ mConstantBuffer->Update();
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::vectorTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRGName(context->GetStringTable().RegisterStr("rg"));
+ mConstantBuffer->AddParam(theRGName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBAName(context->GetStringTable().RegisterStr("ba"));
+ mConstantBuffer->AddParam(theBAName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+
+ // set values
+ QT3DSVec2 rg;
+ rg[0] = 0.0;
+ rg[1] = 1.0;
+ mConstantBuffer->UpdateParam("rg", NVDataRef<QT3DSU8>((QT3DSU8 *)&rg, 1));
+ QT3DSVec2 ba;
+ ba[0] = 0.0;
+ ba[1] = 1.0;
+ mConstantBuffer->UpdateParam("ba", NVDataRef<QT3DSU8>((QT3DSU8 *)&ba, 1));
+ mConstantBuffer->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::vectorTest",
+ toRef(vectorVertShader(isGLESContext(context), vtxProg)),
+ toRef(vectorFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestConstantBuffer::vectorTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestConstantBuffer::vectorTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::structTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static, 0,
+ NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theRGName(context->GetStringTable().RegisterStr("s[0].rg"));
+ mConstantBuffer->AddParam(theRGName, NVRenderShaderDataTypes::QT3DSVec2, 1);
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("s[0].mat_mvp"));
+ mConstantBuffer->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("s[0].blue"));
+ mConstantBuffer->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theAlphaName(context->GetStringTable().RegisterStr("s[0].alpha"));
+ mConstantBuffer->AddParam(theAlphaName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ QT3DSVec2 rg;
+ rg[0] = 0.0;
+ rg[1] = 1.0;
+ mConstantBuffer->UpdateParam("s[0].rg", NVDataRef<QT3DSU8>((QT3DSU8 *)&rg, 1));
+ QT3DSF32 blue, alpha;
+ blue = 0.0;
+ alpha = 1.0;
+ mConstantBuffer->UpdateParam("s[0].blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+ mConstantBuffer->UpdateParam("s[0].alpha", NVDataRef<QT3DSU8>((QT3DSU8 *)&alpha, 1));
+ mConstantBuffer->UpdateParam("s[0].mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::structTest",
+ toRef(structVertShader(isGLESContext(context), vtxProg)),
+ toRef(structFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestConstantBuffer::structTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestConstantBuffer::structTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestConstantBuffer::rawTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ struct sampleStruct
+ {
+ float rg[2];
+ float padding[2];
+ QT3DSMat44 mat_mvp; // matrices start on 16 byte boundaries
+ float blue;
+ float alpha;
+ } s;
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ NVDataRef<QT3DSU8> cBuffer((QT3DSU8 *)&s, sizeof(sampleStruct));
+ // create constant buffer referred in the program
+ mConstantBuffer = context->CreateConstantBuffer("cbBuffer", NVRenderBufferUsageType::Static,
+ sizeof(sampleStruct), cBuffer);
+ // set values
+ s.rg[0] = 0.0;
+ s.rg[1] = 1.0;
+ s.mat_mvp = mvp;
+ s.blue = 0.0;
+ s.alpha = 0.0;
+ mConstantBuffer->UpdateRaw(0, cBuffer);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::rawTest",
+ toRef(structVertShader(isGLESContext(context), vtxProg)),
+ toRef(structFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestConstantBuffer::rawTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestConstantBuffer::rawTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cb("cbBuffer",
+ *compResult.mShader);
+ cb.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+///< test of multiple constant buffers
+bool NVRenderTestConstantBuffer::multiCBTest(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBufferTrans;
+ NVScopedRefCounted<NVRenderConstantBuffer> mConstantBufferCol;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create constant buffer referred in the program
+ mConstantBufferTrans = context->CreateConstantBuffer(
+ "cbBufferTrans", NVRenderBufferUsageType::Static, 0, NVDataRef<QT3DSU8>());
+ // buffer parameter. They must be in the order of appearance
+ CRegisteredString theMatName(context->GetStringTable().RegisterStr("mat_mvp"));
+ mConstantBufferTrans->AddParam(theMatName, NVRenderShaderDataTypes::QT3DSMat44, 1);
+
+ // create constant buffer referred in the program
+ mConstantBufferCol = context->CreateConstantBuffer(
+ "cbBufferCol", NVRenderBufferUsageType::Static, 0, NVDataRef<QT3DSU8>());
+ CRegisteredString theRedName(context->GetStringTable().RegisterStr("red"));
+ mConstantBufferCol->AddParam(theRedName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theGreenName(context->GetStringTable().RegisterStr("green"));
+ mConstantBufferCol->AddParam(theGreenName, NVRenderShaderDataTypes::QT3DSF32, 1);
+ CRegisteredString theBlueName(context->GetStringTable().RegisterStr("blue"));
+ mConstantBufferCol->AddParam(theBlueName, NVRenderShaderDataTypes::QT3DSF32, 1);
+
+ // set values
+ mConstantBufferTrans->UpdateParam("mat_mvp", NVDataRef<QT3DSU8>((QT3DSU8 *)mvp.front(), 1));
+
+ QT3DSF32 red = 0.0;
+ mConstantBufferCol->UpdateParam("red", NVDataRef<QT3DSU8>((QT3DSU8 *)&red, 1));
+ QT3DSF32 green = 1.0;
+ mConstantBufferCol->UpdateParam("green", NVDataRef<QT3DSU8>((QT3DSU8 *)&green, 1));
+ QT3DSF32 blue = 0.0;
+ mConstantBufferCol->UpdateParam("blue", NVDataRef<QT3DSU8>((QT3DSU8 *)&blue, 1));
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestConstantBuffer::multiCBTest",
+ toRef(multiCBVertShader(isGLESContext(context), vtxProg)),
+ toRef(multiCBFragShader(isGLESContext(context), frgProg)));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestConstantBuffer::scalarTest: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestConstantBuffer::scalarTest: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cbTrans(
+ "cbBufferTrans", *compResult.mShader);
+ mConstantBufferTrans->Update();
+ cbTrans.Set();
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderConstantBuffer *> cbCol(
+ "cbBufferCol", *compResult.mShader);
+ mConstantBufferCol->Update();
+ cbCol.Set();
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestConstantBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestConstantBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h
new file mode 100644
index 0000000..417e4bb
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestConstantBuffer.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
+#define QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestConstantBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestConstantBuffer();
+ ~NVRenderTestConstantBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool scalarTest(NVRenderContext *context, userContextData *pUserData);
+ bool vectorTest(NVRenderContext *context, userContextData *pUserData);
+ bool structTest(NVRenderContext *context, userContextData *pUserData);
+ bool rawTest(NVRenderContext *context, userContextData *pUserData);
+ bool multiCBTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_CONSTANT_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp
new file mode 100644
index 0000000..4b8044d
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestDrawIndirectBuffer.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderDrawIndirectBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestDrawIndirectBuffer::NVRenderTestDrawIndirectBuffer()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestDrawIndirectBuffer::~NVRenderTestDrawIndirectBuffer()
+{
+}
+
+bool NVRenderTestDrawIndirectBuffer::isSupported(NVRenderContext *context)
+{
+ // This is currently only supported on GL 4 and GLES 3.1
+ // we have no direct check for this but this is the same version
+ if (!context->IsAtomicCounterBufferSupported())
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestDrawIndirectBuffer::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= drawArrayIndirect(context, pUserData);
+ _curTest++;
+ success &= drawElementsIndirect(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestDrawIndirectBuffer::drawArrayIndirect(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderDrawIndirectBuffer> mDrawIndirectBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestDrawIndirectBuffer shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL, toConstDataRef(&strides, 1),
+ toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // create draw indirect buffer
+ DrawArraysIndirectCommand command;
+ command.baseInstance = 0;
+ command.count = 6;
+ command.first = 0;
+ command.primCount = 1;
+ QT3DSU32 commandBufSize = sizeof(DrawArraysIndirectCommand);
+ NVDataRef<QT3DSU8> commandData((QT3DSU8 *)&command, commandBufSize);
+ mDrawIndirectBuffer = context->CreateDrawIndirectBuffer(NVRenderBufferUsageType::Dynamic,
+ commandBufSize, commandData);
+
+ if (!mDrawIndirectBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ mDrawIndirectBuffer->Bind();
+ context->DrawIndirect(mInputAssembler->GetPrimitiveType(), 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestDrawIndirectBuffer::drawElementsIndirect(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 4, 5 };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderDrawIndirectBuffer> mDrawIndirectBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestDrawIndirectBuffer shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // index buffer
+ bufSize = 6 * sizeof(unsigned short);
+ NVDataRef<QT3DSU8> idxData((QT3DSU8 *)indices, bufSize);
+ mIndexBuffer = context->CreateIndexBuffer(
+ NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16, bufSize,
+ NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(indices), bufSize));
+ if (!mIndexBuffer) {
+ qWarning() << "NVRenderTestPrimitives::Triangles: Failed to create index buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create input assembler";
+ return false;
+ }
+
+ // create draw indirect buffer
+ DrawElementsIndirectCommand command;
+ command.baseInstance = 0;
+ command.count = 6;
+ command.firstIndex = 0;
+ command.baseVertex = 0;
+ command.primCount = 1;
+ QT3DSU32 commandBufSize = sizeof(DrawElementsIndirectCommand);
+ NVDataRef<QT3DSU8> commandData((QT3DSU8 *)&command, commandBufSize);
+ mDrawIndirectBuffer = context->CreateDrawIndirectBuffer(NVRenderBufferUsageType::Dynamic,
+ commandBufSize, commandData);
+
+ if (!mDrawIndirectBuffer) {
+ qWarning() << "NVRenderTestAtomicCounterBuffer: Failed to create vertex buffer";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ mDrawIndirectBuffer->Bind();
+ context->DrawIndirect(mInputAssembler->GetPrimitiveType(), 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestDrawIndirectBuffer::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestDrawIndirectBuffer::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h
new file mode 100644
index 0000000..ee37a13
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestDrawIndirectBuffer.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_DRAW_INDIRECT_BUFFER_H
+#define QT3DS_RENDER_TEST_DRAW_INDIRECT_BUFFER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestDrawIndirectBuffer : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestDrawIndirectBuffer();
+ ~NVRenderTestDrawIndirectBuffer();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool drawArrayIndirect(NVRenderContext *context, userContextData *pUserData);
+ bool drawElementsIndirect(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_ATOMIC_COUNTER_BUFFER_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp
new file mode 100644
index 0000000..d3c2423
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestPrimitives.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4(0, 1, 0, 1);\n"
+ "}\n";
+}
+
+NVRenderTestPrimitives::NVRenderTestPrimitives()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestPrimitives::~NVRenderTestPrimitives()
+{
+}
+
+bool NVRenderTestPrimitives::isSupported(NVRenderContext *context)
+{
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestPrimitives::renderPrimitive(NVRenderContext *context,
+ userContextData *pContextData,
+ const Vertex *pVertexData, unsigned int vertexCount,
+ const unsigned short *pIndexData,
+ unsigned int indexCount,
+ NVRenderDrawMode::Enum primType)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestPrimitives shader", toRef(PassthroughVertShader()), toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = vertexCount * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)pVertexData, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestPrimitives::Triangles: Failed to create vertex buffer";
+ return false;
+ }
+
+ // index buffer
+ if (pIndexData && indexCount) {
+ bufSize = indexCount * sizeof(unsigned short);
+ NVDataRef<QT3DSU8> idxData((QT3DSU8 *)pIndexData, bufSize);
+ mIndexBuffer = context->CreateIndexBuffer(
+ NVRenderBufferUsageType::Static, NVRenderComponentTypes::QT3DSU16, bufSize,
+ NVConstDataRef<QT3DSU8>(reinterpret_cast<const QT3DSU8 *>(pIndexData), bufSize));
+ if (!mIndexBuffer) {
+ qWarning() << "NVRenderTestPrimitives::Triangles: Failed to create index buffer";
+ return false;
+ }
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestPrimitives::Triangles: Failed to create inout assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ QT3DSU32 count = (mIndexBuffer.mPtr) ? indexCount : vertexCount;
+ context->Draw(primType, count, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestPrimitives::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= triangles(context, pUserData);
+ _curTest++;
+ success &= triangleStrip(context, pUserData);
+ _curTest++;
+ success &= lines(context, pUserData);
+ _curTest++;
+ success &= lineStrip(context, pUserData);
+ _curTest++;
+ success &= trianglesIndexed(context, pUserData);
+ _curTest++;
+ success &= triangleStripIndexed(context, pUserData);
+ _curTest++;
+ success &= linesIndexed(context, pUserData);
+ _curTest++;
+ success &= lineStripIndexed(context, pUserData);
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestPrimitives::triangles(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.85, -0.9, 0) }, { QT3DSVec3(-0.85, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, NULL, 0,
+ NVRenderDrawMode::Triangles);
+}
+
+bool NVRenderTestPrimitives::triangleStrip(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) } };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, NULL, 0,
+ NVRenderDrawMode::TriangleStrip);
+}
+
+bool NVRenderTestPrimitives::lines(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) }, { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) }, { QT3DSVec3(-0.85f, -0.9f, 0.0f) },
+ { QT3DSVec3(-0.85f, -0.9f, 0.0f) }, { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) }, { QT3DSVec3(0.85f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.85f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) }
+ };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 12, NULL, 0,
+ NVRenderDrawMode::Lines);
+}
+
+bool NVRenderTestPrimitives::lineStrip(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) }, { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 5, NULL, 0,
+ NVRenderDrawMode::LineStrip);
+}
+
+bool NVRenderTestPrimitives::trianglesIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.85, -0.9, 0) }, { QT3DSVec3(-0.85, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 4, 5 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, indices, 6,
+ NVRenderDrawMode::Triangles);
+}
+
+bool NVRenderTestPrimitives::triangleStripIndexed(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, indices, 4,
+ NVRenderDrawMode::TriangleStrip);
+}
+
+bool NVRenderTestPrimitives::linesIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = {
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) }, { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(-0.85f, -0.9f, 0.0f) }, { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.85f, 0.9f, 0.0f) }, { QT3DSVec3(-0.9f, 0.9f, 0.0f) },
+ };
+
+ const unsigned short indices[] = { 0, 1, 1, 2, 2, 0, 3, 4, 4, 5, 5, 3 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 6, indices, 12,
+ NVRenderDrawMode::Lines);
+}
+
+bool NVRenderTestPrimitives::lineStripIndexed(NVRenderContext *context, userContextData *pUserData)
+{
+ const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0.0) },
+ { QT3DSVec3(-0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, -0.9f, 0.0f) },
+ { QT3DSVec3(0.9f, 0.9f, 0.0f) } };
+
+ const unsigned short indices[] = { 0, 1, 2, 3, 0 };
+
+ return renderPrimitive(context, pUserData, vertexPositions, 4, indices, 5,
+ NVRenderDrawMode::LineStrip);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestPrimitives::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestPrimitives::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h
new file mode 100644
index 0000000..4b6128e
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestPrimitives.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_PRIMITIVES_H
+#define QT3DS_RENDER_TEST_PRIMITIVES_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ struct Vertex
+ {
+ QT3DSVec3 positions;
+ };
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestPrimitives : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestPrimitives();
+ ~NVRenderTestPrimitives();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool triangles(NVRenderContext *context, userContextData *pUserData);
+ bool triangleStrip(NVRenderContext *context, userContextData *pUserData);
+ bool lines(NVRenderContext *context, userContextData *pUserData);
+ bool lineStrip(NVRenderContext *context, userContextData *pContextData);
+
+ bool trianglesIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool triangleStripIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool linesIndexed(NVRenderContext *context, userContextData *pUserData);
+ bool lineStripIndexed(NVRenderContext *context, userContextData *pContextData);
+
+ bool renderPrimitive(NVRenderContext *context, userContextData *pContextData,
+ const Vertex *pVertexData, unsigned int vertexCount,
+ const unsigned short *pIndexData, unsigned int indexCount,
+ NVRenderDrawMode::Enum primType);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_PRIMITIVES_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp
new file mode 100644
index 0000000..a76bfa0
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestProgramPipeline.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderProgramPipeline.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+
+ prog += "out gl_PerVertex\n"
+ "{\n"
+ "\tvec4 gl_Position;\n"
+ "\tfloat gl_PointSize;\n"
+ "\tfloat gl_ClipDistance[];\n"
+ "};\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_col; // Vertex col\n"
+ "out vec3 color; // output color\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ " color = attr_col;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ prog += "in vec3 color; // input color\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4( color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+NVRenderTestProgramPipeline::NVRenderTestProgramPipeline()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestProgramPipeline::~NVRenderTestProgramPipeline()
+{
+}
+
+bool NVRenderTestProgramPipeline::isSupported(NVRenderContext *context)
+{
+ return context->IsProgramPipelineSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestProgramPipeline::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= vertFragSeparateTest(context, pUserData);
+ _curTest++;
+ success &= vertFragCombinedTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestProgramPipeline::vertFragSeparateTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderProgramPipeline> mProgramPipeline;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult vtxResult = context->CompileSource(
+ "NVRenderTestProgramPipeline vertex shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+ if (!vtxResult.mShader) {
+ return false;
+ }
+
+ NVRenderVertFragCompilationResult fragResult = context->CompileSource(
+ "NVRenderTestProgramPipeline fragment shader", NVConstDataRef<QT3DSI8>(),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+
+ if (!fragResult.mShader) {
+ return false;
+ }
+
+ // setup program pipeline
+ mProgramPipeline = context->CreateProgramPipeline();
+ if (!mProgramPipeline) {
+ qWarning() << "NVRenderTestProgramPipeline: Failed to create program pipeline";
+ return false;
+ }
+
+ mProgramPipeline->SetProgramStages(vtxResult.mShader,
+ NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Vertex));
+ mProgramPipeline->SetProgramStages(fragResult.mShader,
+ NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Fragment));
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveProgramPipeline(mProgramPipeline);
+ vtxResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ vtxResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveProgramPipeline(0);
+ return true;
+}
+
+bool NVRenderTestProgramPipeline::vertFragCombinedTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ static const Vertex vertexColors[] = { { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) },
+ { QT3DSVec3(0.0, 1.0, 0.0) } };
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderVertexBuffer> mColorBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderProgramPipeline> mProgramPipeline;
+ NVRenderVertexBuffer *attribBuffers[2];
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestProgramPipeline vertex shader",
+ toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), NVConstDataRef<QT3DSI8>(), true);
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ // setup program pipeline
+ mProgramPipeline = context->CreateProgramPipeline();
+ if (!mProgramPipeline) {
+ qWarning() << "NVRenderTestProgramPipeline: Failed to create program pipeline";
+ return false;
+ }
+
+ mProgramPipeline->SetProgramStages(
+ compResult.mShader, NVRenderShaderTypeFlags(NVRenderShaderTypeValue::Vertex
+ | NVRenderShaderTypeValue::Fragment));
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0, 0),
+ NVRenderVertexBufferEntry("attr_col", NVRenderComponentTypes::QT3DSF32, 3, 0, 1),
+ };
+
+ // position buffer
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create vertex buffer";
+ return false;
+ }
+ // color buffer
+ NVDataRef<QT3DSU8> colorData((QT3DSU8 *)vertexColors, bufSize);
+ mColorBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), colorData);
+ if (!mColorBuffer) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create color buffer";
+ return false;
+ }
+
+ attribBuffers[0] = mVertexBuffer;
+ attribBuffers[1] = mColorBuffer;
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides[2];
+ QT3DSU32 offsets[2];
+ strides[0] = mVertexBuffer->GetStride();
+ offsets[0] = 0;
+ strides[1] = mColorBuffer->GetStride();
+ offsets[1] = 0;
+
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, NVConstDataRef<NVRenderVertexBuffer *>(attribBuffers, 2), NULL,
+ toConstDataRef(strides, 2), toConstDataRef(offsets, 2), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestAttribBuffers: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveProgramPipeline(mProgramPipeline);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveProgramPipeline(0);
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestProgramPipeline::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestProgramPipeline::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h
new file mode 100644
index 0000000..eeec086
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestProgramPipeline.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
+#define QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestProgramPipeline : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestProgramPipeline();
+ ~NVRenderTestProgramPipeline();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool vertFragSeparateTest(NVRenderContext *context, userContextData *pUserData);
+ bool vertFragCombinedTest(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_PROGRAM_PIPELINE_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp
new file mode 100644
index 0000000..6904955
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTexture2D.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderTexture2D.h"
+#include "render/Qt3DSRenderTexture2DArray.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_uv; // texture coord\n"
+ "out vec3 varTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ " varTexCoord = attr_uv;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform sampler2DArray inTex;\n"
+ "in vec3 varTexCoord;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = texture(inTex, varTexCoord);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec3 texCoord;
+};
+
+static const Vertex vertexPositionsL0[] = {
+ { QT3DSVec3(-0.9, 0.0, 0), QT3DSVec3(0, 0, 0) }, { QT3DSVec3(0.0, 0.9, 0), QT3DSVec3(1, 1, 0) },
+ { QT3DSVec3(-0.9, 0.9, 0), QT3DSVec3(0, 1, 0) }, { QT3DSVec3(-0.9, 0.0, 0), QT3DSVec3(0, 0, 0) },
+ { QT3DSVec3(0.0, 0.0, 0), QT3DSVec3(1, 0, 0) }, { QT3DSVec3(0.0, 0.9, 0), QT3DSVec3(1, 1, 0) }
+};
+
+static const Vertex vertexPositionsL1[] = {
+ { QT3DSVec3(0.0, -0.9, 0), QT3DSVec3(0, 0, 1) }, { QT3DSVec3(0.9, 0.0, 0), QT3DSVec3(1, 1, 1) },
+ { QT3DSVec3(0.0, 0.0, 0), QT3DSVec3(0, 1, 1) }, { QT3DSVec3(0.0, -0.9, 0), QT3DSVec3(0, 0, 1) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec3(1, 0, 1) }, { QT3DSVec3(0.9, 0.0, 0), QT3DSVec3(1, 1, 1) }
+};
+
+#define TEXTURE_LAYER_SIZE 2
+#define TEXTURE_SIZE 64
+#define PATTERN_SIZE 0x8
+
+NVRenderTestTexture2D::NVRenderTestTexture2D()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+ _pTextureData = NULL;
+}
+
+NVRenderTestTexture2D::~NVRenderTestTexture2D()
+{
+}
+
+bool NVRenderTestTexture2D::isSupported(NVRenderContext *context)
+{
+ return context->IsTextureArraySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTexture2D::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ // alloc data
+ _pTextureData = new unsigned char[TEXTURE_SIZE * TEXTURE_SIZE * 4 * TEXTURE_LAYER_SIZE];
+ CreateTexData(_pTextureData);
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= texArray2DTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ if (_pTextureData)
+ delete _pTextureData;
+
+ return success;
+}
+
+void NVRenderTestTexture2D::CreateTexData(unsigned char *_pOutData)
+{
+ if (!_pOutData)
+ return;
+
+ unsigned char *_pData = _pOutData;
+
+ // Create a checkerboard pattern
+ for (int i = 0; i < TEXTURE_LAYER_SIZE; i++) {
+ for (int j = 0; j < TEXTURE_SIZE; j++) {
+ for (int k = 0; k < TEXTURE_SIZE; k++) {
+ unsigned char c = (((j & PATTERN_SIZE) == 0) ^ ((k & PATTERN_SIZE) == 0)) * 255;
+ *_pData++ = 0x0;
+ *_pData++ = c >> i;
+ *_pData++ = 0x0;
+ *_pData++ = 0xFF;
+ }
+ }
+ }
+}
+
+bool NVRenderTestTexture2D::renderTexArrayQuad(NVRenderContext *context, userContextData *pUserData,
+ NVRenderTexture2DArray *pTex, QT3DSU8 *vertexPositions)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTexture2D shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_uv", NVRenderComponentTypes::QT3DSF32, 3, 12),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData(vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestTexture2D: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestTexture2D: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ NVRenderCachedShaderProperty<NVRenderTexture2DArray *> mArrayTexture("inTex",
+ *compResult.mShader);
+ mArrayTexture.Set(pTex);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTexture2D::texArray2DTest(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // create texture
+ NVScopedRefCounted<NVRenderTexture2DArray> mArrayTexture;
+ mArrayTexture = context->CreateTexture2DArray();
+ mArrayTexture->SetTextureData(
+ NVDataRef<QT3DSU8>(_pTextureData, TEXTURE_SIZE * TEXTURE_SIZE * 4 * TEXTURE_LAYER_SIZE), 0,
+ TEXTURE_SIZE, TEXTURE_SIZE, TEXTURE_LAYER_SIZE, NVRenderTextureFormats::RGBA8);
+
+ success &= renderTexArrayQuad(context, pUserData, mArrayTexture, (QT3DSU8 *)vertexPositionsL0);
+ success &= renderTexArrayQuad(context, pUserData, mArrayTexture, (QT3DSU8 *)vertexPositionsL1);
+
+ return success;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTexture2D::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTexture2D::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h
new file mode 100644
index 0000000..5c5de11
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTexture2D.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TEXTURE_2D_H
+#define QT3DS_RENDER_TEST_TEXTURE_2D_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderTexture2D;
+ class NVRenderTexture2DArray;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTexture2D : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTexture2D();
+ ~NVRenderTestTexture2D();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool texArray2DTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderTexArrayQuad(NVRenderContext *context, userContextData *pUserData,
+ NVRenderTexture2DArray *pTex, QT3DSU8 *vertexPositions);
+ void CreateTexData(unsigned char *_pOutData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ unsigned char *_pTextureData;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TEXTURE_2D_H
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp
new file mode 100644
index 0000000..bf8ff0e
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.cpp
@@ -0,0 +1,436 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTimerQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderTimerQuery.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+NVRenderTestTimerQuery::NVRenderTestTimerQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestTimerQuery::~NVRenderTestTimerQuery()
+{
+}
+
+bool NVRenderTestTimerQuery::isSupported(NVRenderContext *context)
+{
+ return context->IsTimerQuerySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTimerQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= timerTest(context, pUserData);
+ _curTest++;
+ success &= absoluteTimerTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestTimerQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTimerQuery::timerTest(NVRenderContext *context, userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+ QT3DSVec3 color(1.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, 0.2);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ NVScopedRefCounted<NVRenderTimerQuery> pQuery = context->CreateTimerQuery();
+
+ // render 1000 quads this should take at least some amount of time
+ pQuery->Begin();
+ for (QT3DSI32 i = 0; i < 1000; i++) {
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+ }
+ pQuery->End();
+
+ // get elapsed time in nano seconds
+ QT3DSU64 result = 0;
+ pQuery->GetResult(&result);
+ // convert to milli second
+ QT3DSF64 elapsed = double(result) / 1e06;
+
+ /// it should take at least a fraction of a milli second
+ if (elapsed > 0.0)
+ color.x = 0.0; // right
+ else
+ color.y = 0.0; // wrong
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ renderQuad(context, pUserData, color);
+
+ return (elapsed > 0.0);
+}
+
+bool NVRenderTestTimerQuery::absoluteTimerTest(NVRenderContext *context, userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+ QT3DSVec3 color(1.0, 1.0, 0.0);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTimerQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestTimerQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, 0.2);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ NVScopedRefCounted<NVRenderTimerQuery> pQueryStart = context->CreateTimerQuery();
+ NVScopedRefCounted<NVRenderTimerQuery> pQueryEnd = context->CreateTimerQuery();
+
+ // render 1000 quads this should take at least some amount of time
+ pQueryStart->SetTimerQuery();
+ for (QT3DSI32 i = 0; i < 1000; i++) {
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+ }
+ pQueryEnd->SetTimerQuery();
+
+ // get absolute time in nano seconds
+ QT3DSU64 start = 0;
+ pQueryStart->GetResult(&start);
+ QT3DSU64 end = 0;
+ pQueryEnd->GetResult(&end);
+
+ // convert to milli second
+ QT3DSF64 elapsed = double(end - start) / 1e06;
+
+ // it should take at least a fraction of a milli second
+ if (elapsed > 0.0)
+ color.x = 0.0; // right
+ else
+ color.y = 0.0; // wrong
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ renderQuad(context, pUserData, color);
+
+ return (elapsed > 0.0);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTimerQuery::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTimerQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h
new file mode 100644
index 0000000..127c25f
--- /dev/null
+++ b/tests/auto/runtime/base/Qt3DSRenderTestTimerQuery.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TIMER_QUERY_H
+#define QT3DS_RENDER_TEST_TIMER_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderTimerQuery;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTimerQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTimerQuery();
+ ~NVRenderTestTimerQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool timerTest(NVRenderContext *context, userContextData *pUserData);
+ bool absoluteTimerTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TIMER_QUERY_H
diff --git a/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp
new file mode 100644
index 0000000..15035b4
--- /dev/null
+++ b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.cpp
@@ -0,0 +1,636 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestComputeShader.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderStorageBuffer.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vertTexShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec2 attr_uv; // texture coord\n"
+ "out vec2 varTexCoord;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ " varTexCoord = attr_uv;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragTexShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform sampler2D inTex;\n"
+ "in vec2 varTexCoord;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = texture(inTex, varTexCoord);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x =16, local_size_y = 16) in;\n\n"
+ "void main()\n"
+ "{\n"
+ " // do nothing\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeWorkShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n"
+ "precision mediump image2D;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n";
+ }
+
+ prog += "// Set workgroup layout;\n"
+ "layout (local_size_x = 32, local_size_y = 32) in;\n\n"
+ "layout (rgba8, binding = 2) uniform image2D outputImage;\n\n"
+ "void main()\n"
+ "{\n"
+ " imageStore( outputImage, ivec2(gl_GlobalInvocationID.xy), vec4( "
+ "vec2(gl_LocalInvocationID.xy) / vec2(gl_WorkGroupSize.xy), 0.0, 1.0 ) );\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *computeStorageShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "#extension GL_ARB_shader_storage_buffer_object : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n"
+ "#extension GL_ARB_compute_shader : enable\n"
+ "#extension GL_ARB_shader_storage_buffer_object : enable\n";
+ }
+
+ prog += "layout( std140, binding=4 ) buffer Pos\n"
+ "{\n"
+ " vec4 Positions[ ]; // array of positions\n"
+ "};\n"
+ "// Set workgroup layout;\n"
+ "layout (local_size_x = 32, local_size_y = 1) in;\n\n"
+ "void main()\n"
+ "{\n"
+ " uint gid = gl_GlobalInvocationID.x;\n"
+ " if ( gid < uint(1000) ) {\n"
+ " Positions[gid].x = float(gl_GlobalInvocationID.x);\n"
+ " }\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec2 texCoord;
+};
+
+NVRenderTestComputeShader::NVRenderTestComputeShader()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestComputeShader::~NVRenderTestComputeShader()
+{
+}
+
+bool NVRenderTestComputeShader::isSupported(NVRenderContext *context)
+{
+ return context->IsComputeSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestComputeShader::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= computeCompile(context, pUserData);
+ _curTest++;
+ success &= computeWorkgroup(context, pUserData);
+ _curTest++;
+ success &= computeStorage(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestComputeShader::computeCompile(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which does nothing just as a compile check
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute nothing shader", toRef(computeShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ return true;
+}
+
+#define WORKGROUP_SIZE 32
+
+bool NVRenderTestComputeShader::computeWorkgroup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = {
+ { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) }, { QT3DSVec3(0.9, 0.9, 0), QT3DSVec2(1, 1) },
+ { QT3DSVec3(-0.9, 0.9, 0), QT3DSVec2(0, 1) }, { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(1, 0) }, { QT3DSVec3(0.9, 0.9, 0), QT3DSVec2(1, 1) }
+ };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ // create texture
+ NVScopedRefCounted<NVRenderTexture2D> mColorTexture;
+ mColorTexture = context->CreateTexture2D();
+ mColorTexture->SetTextureStorage(1, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::RGBA8);
+ // create a image buffer wrapper
+ NVScopedRefCounted<NVRenderImage2D> mColorImage;
+ mColorImage = context->CreateImage2D(mColorTexture, NVRenderImageAccessType::Write);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertTexShader(vtxProg, isGLESContext(context))),
+ toRef(fragTexShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_uv", NVRenderComponentTypes::QT3DSF32, 2, 12),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which outputs the workgroups as color codes
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute workgroup shader", toRef(computeWorkShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create compute shader";
+ return false;
+ }
+
+ // set program
+ context->SetActiveShader(computeResult.mShader);
+ NVRenderCachedShaderProperty<NVRenderImage2D *> mOutputImage("outputImage",
+ *computeResult.mShader);
+ mOutputImage.Set(mColorImage);
+ // run compute shader
+ context->DispatchCompute(computeResult.mShader, pUserData->winWidth / WORKGROUP_SIZE,
+ pUserData->winHeight / WORKGROUP_SIZE, 1);
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderImageAccess);
+ // sync
+ context->SetMemoryBarrier(flags);
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set texture
+ NVRenderCachedShaderProperty<NVRenderTexture2D *> mInputImage("inTex", *compResult.mShader);
+ mInputImage.Set(mColorTexture);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 6, 0);
+
+ context->SetActiveShader(0);
+
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestComputeShader::computeStorage(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create vertex buffer for compute shader usage
+ NVScopedRefCounted<NVRenderVertexBuffer> mComputeVertexBuffer;
+ QT3DSF32 *storageData = new QT3DSF32[1000 * 4]; // vec 4 in shader program
+ NVDataRef<QT3DSU8> storData((QT3DSU8 *)storageData, 1000 * sizeof(QT3DSF32) * 4);
+ mComputeVertexBuffer = context->CreateVertexBuffer(
+ NVRenderBufferUsageType::Static, 1000 * sizeof(QT3DSF32) * 4, sizeof(QT3DSF32), storData);
+ if (!mComputeVertexBuffer) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create compute vertex buffer";
+ return false;
+ }
+ // create storage wrapper for vertex buffer
+ NVScopedRefCounted<NVRenderStorageBuffer> mComputeStorageBuffer;
+ mComputeStorageBuffer =
+ context->CreateStorageBuffer("Pos", NVRenderBufferUsageType::Static,
+ 1000 * sizeof(QT3DSF32) * 4, storData, mComputeVertexBuffer.mPtr);
+ if (!mComputeStorageBuffer) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create compute storage buffer";
+ return false;
+ }
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestComputeShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a compute shader which places id's into the buffer
+ std::string computeProg;
+ NVRenderVertFragCompilationResult computeResult = context->CompileComputeSource(
+ "Compute storage shader", toRef(computeStorageShader(computeProg, isGLESContext(context))));
+
+ if (!computeResult.mShader) {
+ qWarning() << "NVRenderTestComputeShader: Failed to create compute shader";
+ return false;
+ }
+
+ // set and run compute program
+ context->SetActiveShader(computeResult.mShader);
+ qt3ds::render::NVRenderCachedShaderBuffer<NVRenderShaderStorageBuffer *> storageBuffer(
+ "Pos", *computeResult.mShader);
+ storageBuffer.Set();
+ // run compute shader
+ context->DispatchCompute(computeResult.mShader, 1024 / WORKGROUP_SIZE, 1, 1);
+ NVRenderBufferBarrierFlags flags(NVRenderBufferBarrierValues::ShaderStorage
+ | NVRenderBufferBarrierValues::VertexAttribArray);
+ // sync
+ context->SetMemoryBarrier(flags);
+
+ // check content
+ bool contentOK = true;
+ mComputeVertexBuffer->Bind();
+ NVDataRef<QT3DSU8> pData = mComputeVertexBuffer->MapBuffer();
+ QT3DSF32 *fData = (QT3DSF32 *)pData.begin();
+ QT3DSU32 size = pData.size() / 4;
+ for (QT3DSU32 i = 0, k = 0; i < size; i += 4, k++) {
+ if (fData[i] != (float)k)
+ contentOK = false;
+ }
+
+ mComputeVertexBuffer->UnmapBuffer();
+
+ if (!contentOK) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (computeResult.mShader)
+ computeResult.mShader->release();
+
+ delete storageData;
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestComputeShader::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestComputeShader::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h
new file mode 100644
index 0000000..826fb9c
--- /dev/null
+++ b/tests/auto/runtime/compute/Qt3DSRenderTestComputeShader.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_COMPUTE_SHADER_H
+#define QT3DS_RENDER_TEST_COMPUTE_SHADER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestComputeShader : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestComputeShader();
+ ~NVRenderTestComputeShader();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool computeCompile(NVRenderContext *context, userContextData *pUserData);
+ bool computeWorkgroup(NVRenderContext *context, userContextData *pUserData);
+ bool computeStorage(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp
new file mode 100644
index 0000000..400cfc5
--- /dev/null
+++ b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestFboMsaa.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *PassthroughVertShader()
+{
+ return "uniform mat4 mat_mvp;\n"
+ "attribute vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+}
+
+static const char *SimpleFragShader()
+{
+ return "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform vec3 color;\n"
+ "void main()\n"
+ "{\n"
+ "gl_FragColor = vec4( color, 1.0);\n"
+ "}\n";
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+NVRenderTestFboMsaa::NVRenderTestFboMsaa()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestFboMsaa::~NVRenderTestFboMsaa()
+{
+}
+
+bool NVRenderTestFboMsaa::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(NVRenderContextValues::GL2 | NVRenderContextValues::GLES2
+ | NVRenderContextValues::GLES3);
+
+ // This is currently only supported on >= GL3 && >= GLES 3.1
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+bool NVRenderTestFboMsaa::run(NVRenderContext *context, userContextData *pUserData)
+{
+ if (!setupResolveFbo(context, pUserData))
+ return false;
+
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetRenderTarget(NULL);
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= simpleMsaaTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestFboMsaa::renderTriangle(NVRenderContext *context, QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ NVRenderVertFragCompilationResult compResult =
+ context->CompileSource("NVRenderTestBackendQuery shader", toRef(PassthroughVertShader()),
+ toRef(SimpleFragShader()));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestFboMsaa::setupResolveFbo(NVRenderContext *context, userContextData *pUserData)
+{
+ // color texture
+ m_ResolveColorTexture = context->CreateTexture2D();
+ m_ResolveColorTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, pUserData->winWidth,
+ pUserData->winHeight, NVRenderTextureFormats::RGBA8);
+ // depth texture
+ m_ResolveDepthTexture = context->CreateTexture2D();
+ m_ResolveDepthTexture->SetTextureData(NVDataRef<QT3DSU8>(), 0, pUserData->winWidth,
+ pUserData->winHeight, NVRenderTextureFormats::Depth24);
+ // create resolve FBO
+ m_ResolveFbo = context->CreateFrameBuffer();
+ m_ResolveFbo->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*m_ResolveColorTexture));
+ m_ResolveFbo->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*m_ResolveDepthTexture));
+
+ return m_ResolveFbo->IsComplete();
+}
+
+bool NVRenderTestFboMsaa::simpleMsaaTest(NVRenderContext *context, userContextData *pUserData)
+{
+ // create a multisampled FBO
+ NVScopedRefCounted<NVRenderFrameBuffer> msFBO;
+ NVScopedRefCounted<NVRenderTexture2D> msColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> msDepth24Texture;
+
+ msColorTexture = context->CreateTexture2D();
+ msColorTexture->SetTextureDataMultisample(4, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::RGBA8);
+ msDepth24Texture = context->CreateTexture2D();
+ msDepth24Texture->SetTextureDataMultisample(4, pUserData->winWidth, pUserData->winHeight,
+ NVRenderTextureFormats::Depth24);
+
+ msFBO = context->CreateFrameBuffer();
+ msFBO->Attach(NVRenderFrameBufferAttachments::Color0,
+ NVRenderTextureOrRenderBuffer(*msColorTexture),
+ NVRenderTextureTargetType::Texture2D_MS);
+ msFBO->Attach(NVRenderFrameBufferAttachments::Depth,
+ NVRenderTextureOrRenderBuffer(*msDepth24Texture),
+ NVRenderTextureTargetType::Texture2D_MS);
+
+ if (!msFBO->IsComplete())
+ return false;
+
+ // clear and draw to multisampled buffer
+ context->SetRenderTarget(msFBO);
+ context->SetMultisampleEnabled(true);
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+ renderTriangle(context, qt3ds::QT3DSVec3(0.0, 1.0, 0.0));
+ context->SetMultisampleEnabled(false);
+
+ // do resolve blit
+ // first we must setup the render target
+ context->SetRenderTarget(m_ResolveFbo);
+ // second setup read target
+ context->SetReadTarget(msFBO);
+ context->SetReadBuffer(NVReadFaces::Color0);
+
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->BlitFramebuffer(0, 0, pUserData->winWidth, pUserData->winHeight, 0, 0,
+ pUserData->winWidth, pUserData->winHeight, NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+
+ // copy to default buffer
+ // first we must setup the render target
+ context->SetRenderTarget(NULL);
+ // second setup read target
+ context->SetReadTarget(m_ResolveFbo);
+ context->SetReadBuffer(NVReadFaces::Color0);
+
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->BlitFramebuffer(0, 0, pUserData->winWidth, pUserData->winHeight, 0, 0,
+ pUserData->winWidth, pUserData->winHeight, NVRenderClearValues::Color,
+ NVRenderTextureMagnifyingOp::Nearest);
+
+ context->SetReadTarget(NULL);
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestFboMsaa::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestFboMsaa::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ m_ResolveColorTexture->release();
+ m_ResolveDepthTexture->release();
+ m_ResolveFbo->release();
+
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ context->SetRenderTarget(NULL);
+}
diff --git a/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h
new file mode 100644
index 0000000..bf9ed84
--- /dev/null
+++ b/tests/auto/runtime/fbo/Qt3DSRenderTestFboMsaa.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_FBO_MSAA_H
+#define QT3DS_RENDER_TEST_FBO_MSAA_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestFboMsaa : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestFboMsaa();
+ ~NVRenderTestFboMsaa();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool setupResolveFbo(NVRenderContext *context, userContextData *pUserData);
+ bool renderTriangle(NVRenderContext *context, QT3DSVec3 color);
+
+ // tests
+ bool simpleMsaaTest(NVRenderContext *context, userContextData *pUserData);
+
+ NVScopedRefCounted<NVRenderFrameBuffer> m_ResolveFbo;
+ NVScopedRefCounted<NVRenderTexture2D> m_ResolveColorTexture;
+ NVScopedRefCounted<NVRenderTexture2D> m_ResolveDepthTexture;
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_FBO_MSAA_H
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp
new file mode 100644
index 0000000..1a1c34c
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.cpp
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestGeometryShader.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderImageTexture.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *geometryShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_geometry_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ // pass through shader
+ prog += "layout (triangles) in;\n"
+ "layout (triangle_strip, max_vertices = 3) out;\n"
+ "void main()\n"
+ "{\n"
+ " int i;\n"
+ " for(i=0; i<gl_in.length(); i++)\n"
+ " {\n"
+ " gl_Position = gl_in[i].gl_Position;\n"
+ " EmitVertex();\n"
+ " }\n"
+ " EndPrimitive();\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *wireframeShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_geometry_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 430\n";
+ }
+
+ // convert to wireframe
+ prog += "layout (triangles) in;\n"
+ "layout (line_strip, max_vertices = 4) out;\n"
+ "void main()\n"
+ "{\n"
+ " int i;\n"
+ " for(i=0; i<gl_in.length(); i++)\n"
+ " {\n"
+ " gl_Position = gl_in[i].gl_Position;\n"
+ " EmitVertex();\n"
+ " }\n"
+ " gl_Position = gl_in[0].gl_Position;\n"
+ " EmitVertex();\n"
+ " EndPrimitive();\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec2 texCoord;
+};
+
+NVRenderTestGeometryShader::NVRenderTestGeometryShader()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestGeometryShader::~NVRenderTestGeometryShader()
+{
+}
+
+bool NVRenderTestGeometryShader::isSupported(NVRenderContext *context)
+{
+ return context->IsGeometryStageSupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestGeometryShader::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= geometryCompile(context, pUserData);
+ _curTest++;
+ success &= wireframe(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestGeometryShader::geometryCompile(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestGeometryShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestGeometryShader: Failed to create input assembler";
+ return false;
+ }
+
+ // create a geometry shader which does nothing just as a compile check
+ std::string geomProg;
+ std::string vtxProgDummy;
+ std::string frgProgDummy;
+ NVRenderVertFragCompilationResult geomResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader",
+ toRef(vertShader(vtxProgDummy, isGLESContext(context))),
+ toRef(fragShader(frgProgDummy, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), toRef(geometryShader(geomProg, isGLESContext(context))));
+
+ if (!geomResult.mShader) {
+ color.x = 1.0;
+ color.y = 0.0;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+ if (geomResult.mShader)
+ geomResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestGeometryShader::wireframe(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.9, -0.9, 0), QT3DSVec2(0, 0) },
+ { QT3DSVec3(0.0, 0.9, 0), QT3DSVec2(0, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ // geometry shader converts primitives from triangles to lines
+ std::string vtxProg;
+ std::string frgProg;
+ std::string geomProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestGeometryShader shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))), NVConstDataRef<QT3DSI8>(),
+ NVConstDataRef<QT3DSI8>(), toRef(wireframeShader(geomProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 5 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestGeometryShader: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Triangles);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestGeometryShader: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestGeometryShader::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestGeometryShader::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h
new file mode 100644
index 0000000..139a7e2
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestGeometryShader.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_GEOMETRY_SHADER_H
+#define QT3DS_RENDER_TEST_GEOMETRY_SHADER_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestGeometryShader : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestGeometryShader();
+ ~NVRenderTestGeometryShader();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool geometryCompile(NVRenderContext *context, userContextData *pUserData);
+ bool wireframe(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp
new file mode 100644
index 0000000..1bb0b16
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.cpp
@@ -0,0 +1,367 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestOcclusionQuery.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderOcclusionQuery.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = mat_mvp * vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 300 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 330\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+};
+
+static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, 0.9, 0) }, { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(-0.9, 0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) }, { QT3DSVec3(0.9, 0.9, 0) } };
+
+static const Vertex largeQuadPositions[] = { { QT3DSVec3(-0.7, 0.7, 0) }, { QT3DSVec3(-0.7, -0.7, 0) },
+ { QT3DSVec3(0.7, -0.7, 0) }, { QT3DSVec3(-0.7, 0.7, 0) },
+ { QT3DSVec3(0.7, -0.7, 0) }, { QT3DSVec3(0.7, 0.7, 0) } };
+
+static const Vertex smallQuadPositions[] = { { QT3DSVec3(-0.5, 0.5, 0) }, { QT3DSVec3(-0.5, -0.5, 0) },
+ { QT3DSVec3(0.5, -0.5, 0) }, { QT3DSVec3(-0.5, 0.5, 0) },
+ { QT3DSVec3(0.5, -0.5, 0) }, { QT3DSVec3(0.5, 0.5, 0) } };
+
+NVRenderTestOcclusionQuery::NVRenderTestOcclusionQuery()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestOcclusionQuery::~NVRenderTestOcclusionQuery()
+{
+}
+
+bool NVRenderTestOcclusionQuery::isSupported(NVRenderContext *context)
+{
+ return context->IsSampleQuerySupported();
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestOcclusionQuery::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= occlusionPassTest(context, pUserData);
+ _curTest++;
+ success &= occlusionFailTest(context, pUserData);
+ _curTest++;
+
+ // cleanup
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+
+ return success;
+}
+
+bool NVRenderTestOcclusionQuery::renderQuad(NVRenderContext *context, userContextData *pUserData,
+ QT3DSVec3 color)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestOcclusionQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 3 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestOcclusionQuery: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler =
+ context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestOcclusionQuery: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+void NVRenderTestOcclusionQuery::renderPrim(NVRenderContext *context, userContextData *pUserData,
+ void *pData, float zOffset, QT3DSVec3 color,
+ NVRenderOcclusionQuery *pQuery)
+{
+ NVScopedRefCounted<NVRenderVertexBuffer> mVB;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mIA;
+ Vertex *pVtxData = (Vertex *)pData;
+ QT3DSMat44 proj = QT3DSMat44::createIdentity();
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&proj, -1, 1, -1, 1, -10, 10);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestOcclusionQuery shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 6 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertDataSmall((QT3DSU8 *)pVtxData, bufSize);
+ mVB = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize, 3 * sizeof(QT3DSF32),
+ vertDataSmall);
+ if (!mVB)
+ qWarning() << "NVRenderTestOcclusionQuery: Failed to create vertex buffer";
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVB->GetStride();
+ QT3DSU32 offsets = 0;
+ mIA = context->CreateInputAssembler(mAttribLayout, toConstDataRef(&mVB.mPtr, 1), NULL,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1));
+ if (!mVB) {
+ qWarning() << "NVRenderTestOcclusionQuery: Failed to create input assembler";
+ return;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mIA);
+ // setup translation
+ QT3DSMat44 transZ;
+ NvRenderTestMatrixTranslation(&transZ, 0.0, 0.0, zOffset);
+ mvp = transZ * proj;
+
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+
+ // start query
+ if (pQuery)
+ pQuery->Begin();
+
+ context->Draw(NVRenderDrawMode::Triangles, 6, 0);
+
+ // end query
+ if (pQuery)
+ pQuery->End();
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+}
+
+bool NVRenderTestOcclusionQuery::occlusionPassTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderOcclusionQuery> pQuery = context->CreateOcclusionQuery();
+
+ renderPrim(context, pUserData, (void *)largeQuadPositions, 0.1, QT3DSVec3(0.0, 0.0, 1.0), NULL);
+ // this quad should be covered by the previous one
+ renderPrim(context, pUserData, (void *)smallQuadPositions, 0.2, QT3DSVec3(1.0, 1.0, 0.0), pQuery);
+ // check visibility
+ QT3DSU32 result = 0;
+ pQuery->GetResult(&result);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ if (result)
+ color.x = 1.0; // wrong
+ else
+ color.y = 1.0; // right
+
+ renderQuad(context, pUserData, color);
+
+ return (result == 0);
+}
+
+bool NVRenderTestOcclusionQuery::occlusionFailTest(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ NVScopedRefCounted<NVRenderOcclusionQuery> pQuery = context->CreateOcclusionQuery();
+
+ renderPrim(context, pUserData, (void *)largeQuadPositions, 0.2, QT3DSVec3(0.0, 0.0, 1.0), NULL);
+ // this quad should be visible by the previous one
+ renderPrim(context, pUserData, (void *)smallQuadPositions, 0.1, QT3DSVec3(1.0, 1.0, 0.0), pQuery);
+ // check visibility
+ QT3DSU32 result = 0;
+ pQuery->GetResult(&result);
+
+ QT3DSVec3 color(0.0, 0.0, 0.0);
+ if (result == 0)
+ color.x = 1.0; // wrong
+ else
+ color.y = 1.0; // right
+
+ renderQuad(context, pUserData, color);
+
+ return (result == 1);
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestOcclusionQuery::runPerformance(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestOcclusionQuery::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(0.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h
new file mode 100644
index 0000000..d540dad
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestOcclusionQuery.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2014 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
+#define QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ class NVRenderOcclusionQuery;
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestOcclusionQuery : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestOcclusionQuery();
+ ~NVRenderTestOcclusionQuery();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool occlusionPassTest(NVRenderContext *context, userContextData *pUserData);
+ bool occlusionFailTest(NVRenderContext *context, userContextData *pUserData);
+
+ bool renderQuad(NVRenderContext *context, userContextData *pUserData, QT3DSVec3 color);
+ void renderPrim(NVRenderContext *context, userContextData *pUserData, void *pData, float z,
+ QT3DSVec3 color, NVRenderOcclusionQuery *pQuery);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_OCCLUSION_QUERY_H
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp
new file mode 100644
index 0000000..f2724a4
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.cpp
@@ -0,0 +1,560 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "Qt3DSRenderTestTessellation.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/backends/gl/Qt3DSOpenGLUtil.h"
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+static const char *vertShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *vertPhongShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform mat4 mat_mvp;\n"
+ "in vec3 attr_pos; // Vertex pos\n"
+ "in vec3 attr_norm; // normal pos\n"
+ "out vec3 ctNorm; // output normal control patch\n"
+ "void main()\n"
+ "{\n"
+ " ctNorm = attr_norm;\n"
+ " gl_Position = vec4(attr_pos, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *fragPhongShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "uniform vec3 color;\n"
+ "in vec3 normWorld;\n"
+ "out vec4 fragColor;\n"
+ "void main()\n"
+ "{\n"
+ " fragColor = vec4(color, 1.0);\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessControlShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// number of CPs in patch\n"
+ "layout (vertices = 3) out;\n"
+ "uniform float tessLevelInner; // controlled by keyboard buttons\n"
+ "uniform float tessLevelOuter; // controlled by keyboard buttons\n"
+ "void main () {\n"
+ "gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ "// Calculate the tessellation levels\n"
+ "gl_TessLevelInner[0] = tessLevelInner; // number of nested primitives to generate\n"
+ "gl_TessLevelOuter[0] = tessLevelOuter; // times to subdivide first side\n"
+ "gl_TessLevelOuter[1] = tessLevelOuter; // times to subdivide second side\n"
+ "gl_TessLevelOuter[2] = tessLevelOuter; // times to subdivide third side\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessPhongControlShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog +=
+ "// number of CPs in patch\n"
+ "layout (vertices = 3) out;\n"
+ "// phong tessellation per patch data\n"
+ "struct PhongTessPatch {\n"
+ " float projIJ;\n"
+ " float projJK;\n"
+ " float projIK;\n"
+ "};\n"
+ "in vec3 ctNorm[]; // control point normal\n"
+ "out vec3 normObj[]; // output normal pos\n"
+ "uniform float tessLevels;\n"
+ "uniform float tessBlend;\n"
+ "out PhongTessPatch tcTessPatch[3];\n"
+ "float PIi(int i, vec3 q)\n"
+ "{\n"
+ " vec3 q_minus_p = q - gl_in[i].gl_Position.xyz;\n"
+ " return q[gl_InvocationID] - dot(q_minus_p, ctNorm[i]) * ctNorm[i][gl_InvocationID];\n"
+ "}\n"
+ "void main () {\n"
+ " // path through data\n"
+ " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+ " normObj[gl_InvocationID] = ctNorm[gl_InvocationID];\n"
+ " // compute projections separate for each xyz component\n"
+ " tcTessPatch[gl_InvocationID].projIJ = PIi(0, gl_in[1].gl_Position.xyz) + PIi(1, "
+ "gl_in[0].gl_Position.xyz);\n"
+ " tcTessPatch[gl_InvocationID].projJK = PIi(1, gl_in[2].gl_Position.xyz) + PIi(2, "
+ "gl_in[1].gl_Position.xyz);\n"
+ " tcTessPatch[gl_InvocationID].projIK = PIi(2, gl_in[0].gl_Position.xyz) + PIi(0, "
+ "gl_in[2].gl_Position.xyz);\n"
+ " // set the tessellation levels\n"
+ " gl_TessLevelInner[0] = tessLevels; // number of nested primitives to generate\n"
+ " gl_TessLevelOuter[gl_InvocationID] = tessLevels; // times to subdivide first side\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessEvaluationShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// triangles, quads, or isolines\n"
+ "layout (triangles, equal_spacing, ccw) in;\n"
+ "uniform mat4 mat_mvp;\n"
+ "// gl_TessCoord is location within the patch\n"
+ "// (barycentric for triangles, UV for quads)\n"
+ "void main () {\n"
+ "vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position; // x is one corner\n"
+ "vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position; // y is the 2nd corner\n"
+ "vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position; // z is the 3rd corner (ignore when "
+ "using quads)\n"
+ "vec4 pos = p0 + p1 + p2;\n"
+ "gl_Position = mat_mvp * pos;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+static const char *tessPhongEvaluationShader(std::string &prog, bool binESContext)
+{
+ if (binESContext) {
+ prog += "#version 310 es\n"
+ "#extension GL_EXT_tessellation_shader : enable\n"
+ "precision highp float;\n"
+ "precision highp int;\n";
+ } else {
+ prog += "#version 400\n";
+ }
+
+ prog += "// triangles, quads, or isolines\n"
+ "layout (triangles, fractional_odd_spacing, ccw) in;\n"
+ "struct PhongTessPatch {\n"
+ " float projIJ;\n"
+ " float projJK;\n"
+ " float projIK;\n"
+ "};\n"
+ "in vec3 normObj[]; // control point normal\n"
+ "out vec3 normWorld; // output normal pos\n"
+ "in PhongTessPatch tcTessPatch[];\n"
+ "uniform mat4 mat_mvp;\n"
+ "uniform float tessBlend;\n"
+ "// gl_TessCoord is location within the patch\n"
+ "// (barycentric for triangles, UV for quads)\n"
+ "void main () {\n"
+ " // output normal\n"
+ " // pre compute square tesselation coord\n"
+ " vec3 tessSquared = gl_TessCoord * gl_TessCoord;\n"
+ " vec3 norm = gl_TessCoord.x * normObj[0]\n"
+ " + gl_TessCoord.y * normObj[1]\n"
+ " + gl_TessCoord.z * normObj[2]; // z is the 3rd corner (ignore when "
+ "using quads)\n"
+ " // barycentric linear position\n"
+ " vec3 linearPos = gl_TessCoord.x * gl_in[0].gl_Position.xyz\n"
+ " + gl_TessCoord.y * gl_in[1].gl_Position.xyz\n"
+ " + gl_TessCoord.z * gl_in[2].gl_Position.xyz;\n"
+ " // projective terms\n"
+ " vec3 projJI = vec3(tcTessPatch[0].projIJ, tcTessPatch[1].projIJ, "
+ "tcTessPatch[2].projIJ);\n"
+ " vec3 projKJ = vec3(tcTessPatch[0].projJK, tcTessPatch[1].projJK, "
+ "tcTessPatch[2].projJK);\n"
+ " vec3 projIK = vec3(tcTessPatch[0].projIK, tcTessPatch[1].projIK, "
+ "tcTessPatch[2].projIK);\n"
+ " // phong interpolated position\n"
+ " vec3 phongPos = tessSquared.x * gl_in[0].gl_Position.xyz\n"
+ " + tessSquared.y * gl_in[1].gl_Position.xyz\n"
+ " + tessSquared.z * gl_in[2].gl_Position.xyz\n"
+ " + gl_TessCoord.x * gl_TessCoord.y * projJI\n"
+ " + gl_TessCoord.y * gl_TessCoord.z * projKJ\n"
+ " + gl_TessCoord.z * gl_TessCoord.x * projIK;\n"
+ " // final position\n"
+ " vec3 finalPos = (1.0-tessBlend)*linearPos + tessBlend*phongPos;\n"
+ " gl_Position = mat_mvp * vec4(finalPos, 1.0);\n"
+ " normWorld = norm;\n"
+ "}\n";
+
+ return prog.c_str();
+}
+
+struct Vertex
+{
+ QT3DSVec3 positions;
+ QT3DSVec3 normals;
+};
+
+NVRenderTestTessellation::NVRenderTestTessellation()
+{
+ _curTest = 0;
+ _maxColumn = 4;
+}
+
+NVRenderTestTessellation::~NVRenderTestTessellation()
+{
+}
+
+bool NVRenderTestTessellation::isSupported(NVRenderContext *context)
+{
+ NVRenderContextType ctxType = context->GetRenderContextType();
+ NVRenderContextType nonSupportedFlags(
+ NVRenderContextValues::GL2 | NVRenderContextValues::GLES2 | NVRenderContextValues::GL3
+ | NVRenderContextValues::GLES3 | NVRenderContextValues::GLES3PLUS);
+
+ // This is currently only supported on >= GL4 && >= GLES 3.1
+ if ((ctxType & nonSupportedFlags))
+ return false;
+
+ return true;
+}
+
+////////////////////////////////
+// test for functionality
+////////////////////////////////
+
+inline NVConstDataRef<QT3DSI8> toRef(const char *data)
+{
+ size_t len = strlen(data) + 1;
+ return NVConstDataRef<QT3DSI8>((const QT3DSI8 *)data, (QT3DSU32)len);
+}
+
+bool NVRenderTestTessellation::run(NVRenderContext *context, userContextData *pUserData)
+{
+ bool success = true;
+
+ context->SetRenderTarget(NULL);
+ // conpute cell width
+ _cellSize = pUserData->winWidth / _maxColumn;
+
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 1.f));
+ context->Clear(NVRenderClearFlags(NVRenderClearValues::Color | NVRenderClearValues::Depth));
+
+ success &= trianglePatches(context, pUserData);
+ _curTest++;
+ success &= phongPatches(context, pUserData);
+ _curTest++;
+
+ return success;
+}
+
+bool NVRenderTestTessellation::trianglePatches(NVRenderContext *context, userContextData *pUserData)
+{
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0) },
+ { QT3DSVec3(0.9, -0.9, 0) },
+ { QT3DSVec3(0.0, 0.9, 0) } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&mvp, -1, 1, -1, 1, -10, 10);
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ std::string tcProg;
+ std::string teProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTessellation shader", toRef(vertShader(vtxProg, isGLESContext(context))),
+ toRef(fragShader(frgProg, isGLESContext(context))),
+ toRef(tessControlShader(tcProg, isGLESContext(context))),
+ toRef(tessEvaluationShader(teProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 1));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Patches, 3);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set tessellation values
+ float tessLevelInner = 4.0;
+ compResult.mShader->SetPropertyValue("tessLevelInner", tessLevelInner);
+ float tessLevelOuter = 4.0;
+ compResult.mShader->SetPropertyValue("tessLevelOuter", tessLevelOuter);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+bool NVRenderTestTessellation::phongPatches(NVRenderContext *context, userContextData *pUserData)
+{
+ QT3DSVec3 n1(-1.0, 0.5, 1.0);
+ n1.normalize();
+ QT3DSVec3 n2(1.0, 0.5, 1.0);
+ n2.normalize();
+ QT3DSVec3 n3(0.0, 1.0, 1.0);
+ n3.normalize();
+ static const Vertex vertexPositions[] = { { QT3DSVec3(-0.9, -0.9, 0.0), n1 },
+ { QT3DSVec3(0.9, -0.9, 0.0), n2 },
+ { QT3DSVec3(0.0, 0.9, -0.0), n3 } };
+
+ qt3ds::QT3DSVec3 color(0.0, 1.0, 0.0);
+
+ NVScopedRefCounted<NVRenderVertexBuffer> mVertexBuffer;
+ NVScopedRefCounted<NVRenderAttribLayout> mAttribLayout;
+ NVScopedRefCounted<NVRenderInputAssembler> mInputAssembler;
+ NVScopedRefCounted<NVRenderIndexBuffer> mIndexBuffer;
+ QT3DSMat44 p = QT3DSMat44::createIdentity();
+ QT3DSMat44 rotX = QT3DSMat44::createIdentity();
+ QT3DSMat44 rotY = QT3DSMat44::createIdentity();
+ QT3DSMat44 mv = QT3DSMat44::createIdentity();
+ QT3DSMat44 mvp = QT3DSMat44::createIdentity();
+ NvGl2DemoMatrixOrtho(&p, -1, 1, -1, 1, -10, 10);
+ // NvRenderTestMatrixRotY( &rotY, 45.0 );
+ // NvRenderTestMatrixRotX( &rotX, 90.0 );
+ mv = rotY * rotX;
+ mvp = mv * p;
+
+ // create shaders
+ std::string vtxProg;
+ std::string frgProg;
+ std::string tcProg;
+ std::string teProg;
+ NVRenderVertFragCompilationResult compResult = context->CompileSource(
+ "NVRenderTestTessellation shader", toRef(vertPhongShader(vtxProg, isGLESContext(context))),
+ toRef(fragPhongShader(frgProg, isGLESContext(context))),
+ toRef(tessPhongControlShader(tcProg, isGLESContext(context))),
+ toRef(tessPhongEvaluationShader(teProg, isGLESContext(context))));
+ if (!compResult.mShader) {
+ return false;
+ }
+
+ unsigned int curY = 0;
+ unsigned int curX = _curTest;
+ if (_curTest >= _maxColumn) {
+ curY = (_curTest / _maxColumn);
+ curX = (_curTest % _maxColumn);
+ }
+
+ // set viewport
+ context->SetViewport(NVRenderRect(curX * _cellSize, curY * _cellSize, _cellSize, _cellSize));
+
+ // this is the layout
+ NVRenderVertexBufferEntry entries[] = {
+ NVRenderVertexBufferEntry("attr_pos", NVRenderComponentTypes::QT3DSF32, 3, 0),
+ NVRenderVertexBufferEntry("attr_norm", NVRenderComponentTypes::QT3DSF32, 3, 12),
+ };
+
+ QT3DSU32 bufSize = 3 * sizeof(Vertex);
+ NVDataRef<QT3DSU8> vertData((QT3DSU8 *)vertexPositions, bufSize);
+ mVertexBuffer = context->CreateVertexBuffer(NVRenderBufferUsageType::Static, bufSize,
+ 6 * sizeof(QT3DSF32), vertData);
+ if (!mVertexBuffer) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create vertex buffer";
+ return false;
+ }
+
+ // create our attribute layout
+ mAttribLayout = context->CreateAttributeLayout(toConstDataRef(entries, 2));
+ // create input Assembler
+ QT3DSU32 strides = mVertexBuffer->GetStride();
+ QT3DSU32 offsets = 0;
+ mInputAssembler = context->CreateInputAssembler(
+ mAttribLayout, toConstDataRef(&mVertexBuffer.mPtr, 1), mIndexBuffer.mPtr,
+ toConstDataRef(&strides, 1), toConstDataRef(&offsets, 1), NVRenderDrawMode::Patches, 3);
+ if (!mInputAssembler) {
+ qWarning() << "NVRenderTestFboMsaa: Failed to create input assembler";
+ return false;
+ }
+
+ // make input assembler active
+ context->SetInputAssembler(mInputAssembler);
+ // set program
+ context->SetActiveShader(compResult.mShader);
+ compResult.mShader->SetPropertyValue("mat_mvp", mvp);
+ // set color
+ compResult.mShader->SetPropertyValue("color", color);
+ // set tessellation values
+ float tessLevels = 8.0;
+ compResult.mShader->SetPropertyValue("tessLevels", tessLevels);
+ float tessBlend = 1.0;
+ compResult.mShader->SetPropertyValue("tessBlend", tessBlend);
+
+ context->SetDepthTestEnabled(true);
+ context->SetDepthWriteEnabled(true);
+
+ // draw
+ context->Draw(mInputAssembler->GetPrimitiveType(), 3, 0);
+
+ context->SetActiveShader(0);
+ compResult.mShader->release();
+
+ return true;
+}
+
+////////////////////////////////
+// performance test
+////////////////////////////////
+bool NVRenderTestTessellation::runPerformance(NVRenderContext *context, userContextData *pUserData)
+{
+ return true;
+}
+
+////////////////////////////////
+// test cleanup
+////////////////////////////////
+void NVRenderTestTessellation::cleanup(NVRenderContext *context, userContextData *pUserData)
+{
+ context->SetClearColor(QT3DSVec4(.0f, .0f, .0f, 0.f));
+ // dummy
+ context->SetViewport(NVRenderRect(0, 0, pUserData->winWidth, pUserData->winHeight));
+}
diff --git a/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h
new file mode 100644
index 0000000..7403696
--- /dev/null
+++ b/tests/auto/runtime/geometry/Qt3DSRenderTestTessellation.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QT3DS_RENDER_TEST_TESSELLATION_H
+#define QT3DS_RENDER_TEST_TESSELLATION_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+ /// This class tests the creation of all kinds of primitives
+ class NVRenderTestTessellation : public NVRenderTestBase
+ {
+ public:
+ NVRenderTestTessellation();
+ ~NVRenderTestTessellation();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+ private:
+ bool trianglePatches(NVRenderContext *context, userContextData *pUserData);
+ bool phongPatches(NVRenderContext *context, userContextData *pUserData);
+
+ unsigned int _curTest;
+ unsigned int _cellSize;
+ unsigned int _maxColumn;
+ };
+}
+}
+
+#endif // QT3DS_RENDER_TEST_TESSELLATION_H
diff --git a/tests/auto/runtime/images/NVRenderTestAttribBuffers.png b/tests/auto/runtime/images/NVRenderTestAttribBuffers.png
new file mode 100644
index 0000000..e0fe946
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestAttribBuffers.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestBackendQuery.png b/tests/auto/runtime/images/NVRenderTestBackendQuery.png
new file mode 100644
index 0000000..7659236
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestBackendQuery.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestClear.png b/tests/auto/runtime/images/NVRenderTestClear.png
new file mode 100644
index 0000000..6e4c319
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestClear.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestComputeShader.png b/tests/auto/runtime/images/NVRenderTestComputeShader.png
new file mode 100644
index 0000000..6f08814
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestComputeShader.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png b/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png
new file mode 100644
index 0000000..7659236
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestDrawIndirectBuffer.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestFboMsaa.png b/tests/auto/runtime/images/NVRenderTestFboMsaa.png
new file mode 100644
index 0000000..8eab95c
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestFboMsaa.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestGeometryShader.png b/tests/auto/runtime/images/NVRenderTestGeometryShader.png
new file mode 100644
index 0000000..820534e
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestGeometryShader.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png b/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png
new file mode 100644
index 0000000..7659236
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestOcclusionQuery.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestProgramPipeline.png b/tests/auto/runtime/images/NVRenderTestProgramPipeline.png
new file mode 100644
index 0000000..f868b2d
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestProgramPipeline.png
Binary files differ
diff --git a/tests/auto/runtime/images/NVRenderTestTexture2D.png b/tests/auto/runtime/images/NVRenderTestTexture2D.png
new file mode 100644
index 0000000..afde59f
--- /dev/null
+++ b/tests/auto/runtime/images/NVRenderTestTexture2D.png
Binary files differ
diff --git a/tests/auto/runtime/runtime.pro b/tests/auto/runtime/runtime.pro
new file mode 100644
index 0000000..995c901
--- /dev/null
+++ b/tests/auto/runtime/runtime.pro
@@ -0,0 +1,82 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../commoninclude.pri)
+
+TARGET = tst_qt3dsruntime
+QT += testlib gui
+QT += quick-private
+
+RESOURCES += \
+ runtime.qrc
+
+INCLUDEPATH += \
+ $$PWD/../../../src/Qt3DSRuntimeRender/RendererImpl
+
+HEADERS += \
+ base/Qt3DSRenderTestAtomicCounterBuffer.h \
+ base/Qt3DSRenderTestAttribBuffers.h \
+ base/Qt3DSRenderTestBackendQuery.h \
+ base/Qt3DSRenderTestClear.h \
+ base/Qt3DSRenderTestConstantBuffer.h \
+ base/Qt3DSRenderTestDrawIndirectBuffer.h \
+ base/Qt3DSRenderTestPrimitives.h \
+ base/Qt3DSRenderTestProgramPipeline.h \
+ base/Qt3DSRenderTestTexture2D.h \
+ base/Qt3DSRenderTestTimerQuery.h \
+ compute/Qt3DSRenderTestComputeShader.h \
+ fbo/Qt3DSRenderTestFboMsaa.h \
+ geometry/Qt3DSRenderTestGeometryShader.h \
+ geometry/Qt3DSRenderTestOcclusionQuery.h \
+ geometry/Qt3DSRenderTestTessellation.h \
+ Qt3DSRenderTestBase.h \
+ Qt3DSRenderTestMathUtil.h \
+ tst_qt3dsruntime.h \
+ shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h \
+ shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h \
+ shadergenerator/Qt3DSRenderTestEffectGenerator.h
+
+SOURCES += \
+ base/Qt3DSRenderTestAtomicCounterBuffer.cpp \
+ base/Qt3DSRenderTestAttribBuffers.cpp \
+ base/Qt3DSRenderTestBackendQuery.cpp \
+ base/Qt3DSRenderTestClear.cpp \
+ base/Qt3DSRenderTestConstantBuffer.cpp \
+ base/Qt3DSRenderTestDrawIndirectBuffer.cpp \
+ base/Qt3DSRenderTestPrimitives.cpp \
+ base/Qt3DSRenderTestProgramPipeline.cpp \
+ base/Qt3DSRenderTestTexture2D.cpp \
+ base/Qt3DSRenderTestTimerQuery.cpp \
+ compute/Qt3DSRenderTestComputeShader.cpp \
+ fbo/Qt3DSRenderTestFboMsaa.cpp \
+ geometry/Qt3DSRenderTestGeometryShader.cpp \
+ geometry/Qt3DSRenderTestOcclusionQuery.cpp \
+ geometry/Qt3DSRenderTestTessellation.cpp \
+ Qt3DSRenderTestMathUtil.cpp \
+ tst_qt3dsruntime.cpp \
+ Qt3DSRenderTestBase.cpp \
+ shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp \
+ shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp \
+ shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
+
+linux {
+ BEGIN_ARCHIVE = -Wl,--whole-archive
+ END_ARCHIVE = -Wl,--no-whole-archive
+}
+
+LIBS += \
+ -lqt3dsopengl$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsqmlstreamer.so
+
+win32 {
+ LIBS += \
+ -lws2_32
+}
+
+linux {
+ LIBS += \
+ -ldl \
+ -lEGL
+}
diff --git a/tests/auto/runtime/runtime.qrc b/tests/auto/runtime/runtime.qrc
new file mode 100644
index 0000000..f4318f5
--- /dev/null
+++ b/tests/auto/runtime/runtime.qrc
@@ -0,0 +1,14 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/NVRenderTestTexture2D.png</file>
+ <file>images/NVRenderTestProgramPipeline.png</file>
+ <file>images/NVRenderTestAttribBuffers.png</file>
+ <file>images/NVRenderTestBackendQuery.png</file>
+ <file>images/NVRenderTestClear.png</file>
+ <file>images/NVRenderTestComputeShader.png</file>
+ <file>images/NVRenderTestDrawIndirectBuffer.png</file>
+ <file>images/NVRenderTestFboMsaa.png</file>
+ <file>images/NVRenderTestGeometryShader.png</file>
+ <file>images/NVRenderTestOcclusionQuery.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp
new file mode 100644
index 0000000..244065a
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.cpp
@@ -0,0 +1,469 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestCustomMaterialGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "Qt3DSRenderCustomMaterialSystem.h"
+#include "Qt3DSRenderCustomMaterialRenderContext.h"
+#include "Qt3DSRenderCustomMaterialShaderGenerator.h"
+#include "Qt3DSRenderDynamicObjectSystem.h"
+#include "Qt3DSRenderDynamicObjectSystemCommands.h"
+#include "Qt3DSRenderContextCore.h"
+#include "Qt3DSTypes.h"
+#include "Qt3DSRenderRuntimeBinding.h"
+#include "Qt3DSApplication.h"
+#include "Qt3DSInputEngine.h"
+#include "foundation/FileTools.h"
+#include "Qt3DSWindowSystem.h"
+#include "Qt3DSRenderShaderCache.h"
+#include "rendererimpl/Qt3DSRendererImpl.h"
+#include "Qt3DSRenderLight.h"
+#include "Qt3DSRenderUIPLoader.h"
+#include "Qt3DSDMMetaDataTypes.h"
+
+#include <QTime>
+#include <QString>
+#include <QTextStream>
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestCustomMaterialGenerator::Qt3DSRenderTestCustomMaterialGenerator()
+{
+
+}
+
+Qt3DSRenderTestCustomMaterialGenerator::~Qt3DSRenderTestCustomMaterialGenerator()
+{
+
+}
+
+
+bool Qt3DSRenderTestCustomMaterialGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestCustomMaterialGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestCustomMaterialGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+struct CustomTestParams
+{
+ SRenderableObjectFlags flags;
+ dynamic::SDynamicShaderProgramFlags dynamicFlags;
+ QT3DSF32 opacity;
+ SLayer layer;
+ SLayerRenderData layerData;
+ SRenderableImage *images;
+ SLight light[QT3DS_MAX_NUM_LIGHTS];
+ SModel model;
+ SRenderSubset subset;
+ SShaderDefaultMaterialKey shaderkey;
+ SCustomMaterial *material;
+ eastl::vector<SShaderPreprocessorFeature> features;
+ Option<qt3dsdm::SMetaDataCustomMaterial> metaMaterial;
+ SImage dummyImages[SShaderDefaultMaterialKeyProperties::ImageMapCount];
+ eastl::vector<SRenderableImage*> renderableImages;
+ qt3ds::render::Qt3DSRendererImpl *render;
+ SImage iblLightProbe;
+ NVRenderTexture2D *texture;
+
+ CustomTestParams(Qt3DSRendererImpl &impl)
+ : layerData(layer, impl)
+ , images(NULL)
+ , subset(impl.GetContext().GetAllocator())
+ , material(NULL)
+ , render(&impl)
+ , texture(NULL)
+ {
+ }
+ ~CustomTestParams()
+ {
+ if (texture)
+ texture->release();
+ }
+
+ void addRenderableImage(ImageMapTypes::Enum type,
+ SShaderDefaultMaterialKeyProperties::ImageMapNames name)
+ {
+ renderableImages.push_back(new SRenderableImage(type, dummyImages[name]));
+ render->DefaultMaterialShaderKeyProperties().m_ImageMaps[name].SetEnabled(shaderkey, true);
+ }
+ void prepare()
+ {
+ for (unsigned int i = 0; i < renderableImages.size(); i++) {
+ if (i == 0)
+ images = renderableImages[0];
+ else
+ renderableImages[i-1]->m_NextImage = renderableImages[i];
+ }
+ }
+};
+
+struct CustomTestKey
+{
+ unsigned int tessellation : 2;
+ unsigned int wireframe : 1;
+ unsigned int lighting: 1;
+ unsigned int indirectLightmap: 1;
+ unsigned int radiosityLightmap: 1;
+ unsigned int shadowLightmap: 1;
+ unsigned int transparency : 1;
+ unsigned int refraction : 1;
+ unsigned int iblprobe : 1;
+ unsigned int emissiveMap : 1;
+ unsigned int displacementMap : 1;
+ unsigned int diffuse = 1;
+ unsigned int specular = 1;
+ unsigned int glossy = 1;
+ unsigned int cutout = 1;
+ unsigned int transmissive : 1;
+ unsigned int ssao : 1;
+ unsigned int ssdo : 1;
+ unsigned int ssm : 1;
+
+ CustomTestKey(TessModeValues::Enum tess = TessModeValues::NoTess, bool wire = false,
+ bool lights = false, bool indirect = false, bool radiosity = false,
+ bool shadow = false, bool trans = false, bool refract = false, bool ibl = false,
+ bool emissive = false, bool disp = false, bool diff = false,
+ bool spec = false, bool glo = false, bool cut = false, bool transm = false,
+ bool ao = false, bool direct = false, bool shadowssm = false)
+ : tessellation(tess), wireframe(wire), lighting(lights), indirectLightmap(indirect)
+ , radiosityLightmap(radiosity), shadowLightmap(shadow), transparency(trans)
+ , refraction(refract), iblprobe(ibl), emissiveMap(emissive), displacementMap(disp)
+ , diffuse(diff), specular(spec), glossy(glo), cutout(cut), transmissive(transm)
+ , ssao(ao), ssdo(direct), ssm(shadowssm)
+ {
+
+ }
+
+ bool operator == (const CustomTestKey &other) const
+ {
+ uint64_t a = *(uint64_t *)this;
+ uint64_t b = *(uint64_t *)&other;
+ return a == b;
+ }
+
+ QString toString()
+ {
+ QString str;
+ QTextStream stream(&str);
+ stream << "Custom Key tessellation: " << int(tessellation);
+ stream << " wireframe: " << (wireframe ? "true" : "false");
+ stream << " lighting: " << (lighting ? "true" : "false");
+ stream << " indirectLightmap: " << (indirectLightmap ? "true" : "false");
+ stream << " radiosityLightmap: " << (radiosityLightmap ? "true" : "false");
+ stream << " shadowLightmap: " << (shadowLightmap ? "true" : "false");
+ stream << " transparency: " << (transparency ? "true" : "false");
+ stream << " refraction: " << (refraction ? "true" : "false");
+ stream << " iblprobe: " << (iblprobe ? "true" : "false");
+ stream << " emissiveMap: " << (emissiveMap ? "true" : "false");
+ stream << " displacementMap: " << (displacementMap ? "true" : "false");
+ stream << " diffuse: " << (diffuse ? "true" : "false");
+ stream << " specular: " << (specular ? "true" : "false");
+ stream << " glossy: " << (glossy ? "true" : "false");
+ stream << " cutout: " << (cutout ? "true" : "false");
+ stream << " transmissive: " << (transmissive ? "true" : "false");
+ stream << " ssao: " << (ssao ? "true" : "false");
+ stream << " ssdo: " << (ssdo ? "true" : "false");
+ stream << " ssm: " << (ssm ? "true" : "false");
+ return str;
+ }
+};
+
+#define MAX_TEST_KEY ((1llu<<20)-1)
+
+static CustomTestKey randomizeTestKey()
+{
+ uint64_t v = (uint64_t(qrand()))%MAX_TEST_KEY;
+ return *reinterpret_cast<CustomTestKey*>(&v);
+}
+
+CustomTestParams *generateTest(qt3ds::render::Qt3DSRendererImpl *renderImpl,
+ NVRenderContext *context, CustomTestKey key, SCustomMaterial *material)
+{
+ CustomTestParams *params = new CustomTestParams(*renderImpl);
+ params->material = material;
+ params->material->m_ShaderKeyValues = (SCustomMaterialShaderKeyFlags)0;
+ params->material->m_Lightmaps = SLightmaps();
+ params->material->m_DisplacementMap = NULL;
+ params->material->m_EmissiveMap2 = NULL;
+ params->material->m_hasTransparency = false;
+ params->material->m_IblProbe = NULL;
+ params->material->m_hasRefraction = false;
+ switch (key.tessellation) {
+ case 1:
+ params->model.m_TessellationMode = TessModeValues::TessLinear;
+ break;
+ case 2:
+ params->model.m_TessellationMode = TessModeValues::TessPhong;
+ break;
+ case 3:
+ params->model.m_TessellationMode = TessModeValues::TessNPatch;
+ break;
+ default:
+ params->model.m_TessellationMode = TessModeValues::NoTess;
+ break;
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetValue(params->shaderkey, params->model.m_TessellationMode);
+
+ if (key.wireframe && key.tessellation > 0) {
+ params->subset.m_WireframeMode = true;
+ renderImpl->DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ params->shaderkey, true);
+ }
+
+ CRegisteredString lighting =
+ renderImpl->GetContext().GetStringTable().RegisterStr("QT3DS_ENABLE_CG_LIGHTING");
+ params->features.push_back(SShaderPreprocessorFeature(lighting, key.lighting));
+
+ if (key.indirectLightmap) {
+ params->material->m_Lightmaps.m_LightmapIndirect
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapIndirect];
+ params->addRenderableImage(ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ }
+ if (key.radiosityLightmap) {
+ params->material->m_Lightmaps.m_LightmapRadiosity
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapRadiosity];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ }
+ if (key.shadowLightmap) {
+ params->material->m_Lightmaps.m_LightmapShadow
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapShadow];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapShadow);
+ }
+
+ if (key.diffuse)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::diffuse;
+
+ // TODO: emissive mask doesn't work
+// if (key.emissiveMap >= 1) {
+// params->material->m_EmissiveMap2
+// = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap];
+// params->addRenderableImage(ImageMapTypes::Emissive,
+// SShaderDefaultMaterialKeyProperties::EmissiveMap);
+// }
+
+ if (key.specular)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::specular;
+
+ if (key.displacementMap) {
+ params->material->m_DisplacementMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::DisplacementMap];
+ params->material->m_DisplacementMap->m_ImageShaderName
+ = renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("DisplacementMap");
+ params->material->m_DisplaceAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::displace;
+ }
+
+ if (key.iblprobe) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(
+ params->shaderkey, true);
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_LIGHT_PROBE"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+
+ params->material->m_IblProbe = &params->iblLightProbe;
+ params->texture = context->CreateTexture2D();
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::RGBA8;
+ unsigned int data = 0;
+ NVDataRef<QT3DSU8> buffer = toU8DataRef<unsigned int>(data);
+ params->texture->SetTextureData(buffer, 0, 1, 1, format);
+ params->iblLightProbe.m_TextureData.m_Texture = params->texture;
+ } else {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_LIGHT_PROBE"));
+ params->features.push_back(SShaderPreprocessorFeature(str, false));
+ }
+
+ // these requires calculateGlass function in material
+// if (key.transparency) {
+// params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::transparent;
+// params->material->m_hasTransparency = true;
+// }
+// if (key.refraction) {
+// params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::refraction;
+// params->material->m_hasRefraction = true;
+// }
+ if (key.glossy)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::glossy;
+
+ if (key.cutout)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::cutout;
+
+ if (key.transmissive)
+ params->material->m_ShaderKeyValues &= SCustomMaterialShaderKeyValues::transmissive;
+
+ if (key.ssm) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSM"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssao) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSAO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssdo) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSDO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+
+ params->prepare();
+ return params;
+}
+
+bool GenShader(IQt3DSRenderContext &qt3dsContext, CustomTestParams &params)
+{
+ bool success = true;
+ ICustomMaterialShaderGenerator &theMaterialGenerator(qt3dsContext.GetCustomMaterialShaderGenerator());
+
+ SCustomMaterialVertexPipeline thePipeline(&qt3dsContext,
+ params.model.m_TessellationMode);
+
+ for (int i = 0; i < params.metaMaterial->m_CustomMaterialCommands.size(); i++) {
+ dynamic::SCommand &command = *params.metaMaterial->m_CustomMaterialCommands[i];
+ if (command.m_Type == dynamic::CommandTypes::Enum::BindShader) {
+ dynamic::SBindShader *bindShader = static_cast<dynamic::SBindShader *>(&command);
+ NVRenderShaderProgram *theProgram = theMaterialGenerator.GenerateShader(
+ *params.material, params.shaderkey, thePipeline,
+ toConstDataRef(params.features.data(), (QT3DSU32)params.features.size()),
+ params.layerData.m_Lights, params.images,
+ (params.material->m_hasTransparency || params.material->m_hasRefraction),
+ "custom material pipeline-- ", bindShader->m_ShaderPath);
+ if (!theProgram) {
+ success = false;
+ break;
+ }
+ }
+ }
+
+ return success;
+}
+
+bool Qt3DSRenderTestCustomMaterialGenerator::run(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ QVector<CustomTestKey> testKeys;
+ testKeys.push_back(CustomTestKey());
+ testKeys.push_back(CustomTestKey(TessModeValues::TessLinear));
+ testKeys.push_back(CustomTestKey(TessModeValues::TessNPatch));
+ testKeys.push_back(CustomTestKey(TessModeValues::TessPhong));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+ testKeys.push_back(CustomTestKey(TessModeValues::NoTess, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true));
+
+ while (testKeys.size() < 100) {
+ CustomTestKey key = randomizeTestKey();
+ if (!testKeys.contains(key))
+ testKeys.push_back(key);
+ }
+
+ if (success) {
+ CRegisteredString name = context->GetStringTable().RegisterStr("qrc:/copper.shader");
+
+ metadata()->LoadMaterialXMLFile("CustomMaterial", "", "copper", "qrc:/copper.shader");
+ Option<qt3dsdm::SMetaDataCustomMaterial> metaMaterial =
+ metadata()->GetMaterialMetaDataBySourcePath("qrc:/copper.shader");
+
+ if (metaMaterial.hasValue()) {
+ qt3ds::render::IUIPLoader::CreateMaterialClassFromMetaMaterial(
+ name, context->GetFoundation(),
+ qt3dsRenderer()->GetQt3DSContext().GetCustomMaterialSystem(), *metaMaterial,
+ context->GetStringTable());
+ SCustomMaterial *material = qt3dsRenderer()->GetQt3DSContext().GetCustomMaterialSystem()
+ .CreateCustomMaterial(name, qt3dsRenderer()->GetContext().GetAllocator());
+
+ for (CustomTestKey key : testKeys) {
+ CustomTestParams *params = generateTest(qt3dsRenderer(), context, key, material);
+ params->metaMaterial = metaMaterial;
+ success &= GenShader(qt3dsRenderer()->GetQt3DSContext(), *params);
+ if (!success)
+ qDebug () << "failing key: " << key.toString();
+ delete params;
+ }
+ delete material;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h
new file mode 100644
index 0000000..621d20f
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_CUSTOM_MATERIAL_GENERATOR_H
+#define QT3DS_RENDER_TEST_CUSTOM_MATERIAL_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestCustomMaterialGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestCustomMaterialGenerator();
+ ~Qt3DSRenderTestCustomMaterialGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp
new file mode 100644
index 0000000..1e2c07e
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.cpp
@@ -0,0 +1,574 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestDefaultMaterialGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "Qt3DSTypes.h"
+#include "Qt3DSRenderRuntimeBinding.h"
+#include "Qt3DSApplication.h"
+#include "Qt3DSInputEngine.h"
+#include "foundation/FileTools.h"
+#include "Qt3DSWindowSystem.h"
+#include "Qt3DSRenderContextCore.h"
+#include "Qt3DSRenderShaderCache.h"
+#include "rendererimpl/Qt3DSRendererImpl.h"
+#include "Qt3DSRenderLight.h"
+
+#include <QTime>
+
+#include <string>
+
+using namespace qt3ds;
+using namespace qt3ds::render;
+
+
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestDefaultMaterialGenerator::Qt3DSRenderTestDefaultMaterialGenerator()
+{
+
+}
+
+Qt3DSRenderTestDefaultMaterialGenerator::~Qt3DSRenderTestDefaultMaterialGenerator()
+{
+
+}
+
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestDefaultMaterialGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+
+#define MAX_TEST_KEY ((1llu<<32)-1)
+
+struct TestKey
+{
+ unsigned int tessellation: 2;
+ unsigned int wireframe: 1;
+ unsigned int lighting: 2;
+ unsigned int lights: 4;
+ unsigned int indirectLightmap: 1;
+ unsigned int radiosityLightmap: 1;
+ unsigned int lightProbe: 2;
+ unsigned int iblLightProbe: 1;
+ unsigned int iblfow: 1;
+ unsigned int diffuseMap: 2;
+ unsigned int emissiveMap: 2;
+ unsigned int specularModel: 2;
+ unsigned int specularMap: 1;
+ unsigned int specularReflection: 1;
+ unsigned int fresnel: 1;
+ unsigned int bumpmapping: 2;
+ unsigned int displacementMap: 1;
+ unsigned int opacityMap: 1;
+ unsigned int translucencyMap: 1;
+ unsigned int ssm: 1;
+ unsigned int ssdo: 1;
+ unsigned int ssao: 1;
+
+ TestKey(TessModeValues::Enum tess = TessModeValues::NoTess, bool wire = false,
+ DefaultMaterialLighting::Enum lmode = DefaultMaterialLighting::NoLighting,
+ int lightCount = 0, bool indirect = false, bool radio = false, int lprobe = 0,
+ bool iblProbe = false, bool iblf = false, int diffuse = 0, int emissive = 0,
+ DefaultMaterialSpecularModel::Enum sModel = DefaultMaterialSpecularModel::Default,
+ bool sMap = false, bool sRef = false, bool fre = false, int bump = 0,
+ bool disp = false, bool opac = false, bool trans = false, bool shadow = false,
+ bool ao = false, bool directOcc = false)
+ : tessellation(tess), wireframe(wire), lighting(lmode), lights(lightCount)
+ , indirectLightmap(indirect), radiosityLightmap(radio), lightProbe(lprobe)
+ , iblLightProbe(iblProbe), iblfow(iblf), diffuseMap(diffuse), emissiveMap(emissive)
+ , specularModel(sModel), specularMap(sMap), specularReflection(sRef)
+ , fresnel(fre), bumpmapping(bump), displacementMap(disp), opacityMap(opac)
+ , translucencyMap(trans), ssm(shadow), ssao(ao), ssdo(directOcc)
+ {
+
+ }
+
+ bool operator == (const TestKey &other) const
+ {
+ return toInt() == other.toInt();
+ }
+
+ QString toString()
+ {
+ QString str;
+ QTextStream stream(&str);
+
+ stream << " tessellation: " << tessellation;
+ stream << " wireframe: " << (wireframe ? "true" : "false");
+ stream << " lighting: " << lighting;
+ stream << " lights: " << lights;
+ stream << " indirectLightmap: " << (indirectLightmap ? "true" : "false");
+ stream << " radiosityLightmap: " << (radiosityLightmap ? "true" : "false");
+ stream << " lightProbe: " << lightProbe;
+ stream << " iblLightProbe: " << (iblLightProbe ? "true" : "false");
+ stream << " iblfow: " << (iblfow ? "true" : "false");
+ stream << " diffuseMap: " << diffuseMap;
+ stream << " emissiveMap: " << emissiveMap;
+ stream << " specularModel: " << specularModel;
+ stream << " specularMap: " << (specularMap ? "true" : "false");
+ stream << " specularReflection: " << (specularReflection ? "true" : "false");
+ stream << " fresnel: " << (fresnel ? "true" : "false");
+ stream << " bumpmapping: " << bumpmapping;
+ stream << " displacementMap: " << (displacementMap ? "true" : "false");
+ stream << " opacityMap: " << (opacityMap ? "true" : "false");
+ stream << " translucencyMap: " << (translucencyMap ? "true" : "false");
+ stream << " ssm: " << (ssm ? "true" : "false");
+ stream << " ssdo: " << (ssdo ? "true" : "false");
+ stream << " ssao: " << (ssao ? "true" : "false");
+
+ return str;
+ }
+
+ void clampValues()
+ {
+ lighting = qMin(lighting, 2u);
+ if (lighting == 1)
+ lighting = 2;
+ emissiveMap = qMin(emissiveMap, 2u);
+ specularModel = qMin(specularModel, 2u);
+ bumpmapping = qMin(bumpmapping, 2u);
+ lightProbe = 0;
+ if (!iblLightProbe)
+ iblfow = 0;
+ if (!tessellation)
+ wireframe = 0;
+ }
+
+ uint64_t toInt() const
+ {
+ return (*(uint64_t *)this)&MAX_TEST_KEY;
+ }
+};
+
+struct TestParams
+{
+ SRenderableObjectFlags flags;
+ NVConstDataRef<QT3DSMat44> boneGlobals;
+ SRenderSubset subset;
+ SDefaultMaterial material;
+ SModel model;
+ QT3DSMat44 viewProjection;
+ SModelContext modelContext;
+ SRenderableImage *images;
+ SShaderDefaultMaterialKey shaderkey;
+ SSubsetRenderable renderable;
+ eastl::vector<SShaderPreprocessorFeature> features;
+ SLight light[QT3DS_MAX_NUM_LIGHTS];
+ SLayer layer;
+ SLayerRenderData layerData;
+ SImage dummyImages[SShaderDefaultMaterialKeyProperties::ImageMapCount];
+ NVRenderTexture2D *textures[4];
+ eastl::vector<SRenderableImage*> renderableImages;
+ qt3ds::render::Qt3DSRendererImpl *render;
+
+ TestParams(NVRenderContext *context, qt3ds::render::Qt3DSRendererImpl *renderImpl)
+ : subset(context->GetAllocator())
+ , modelContext(model, viewProjection)
+ , images(NULL)
+ , renderable(flags, QT3DSVec3(), *renderImpl, subset, material, modelContext, 1.0f, images,
+ shaderkey, boneGlobals)
+ , layerData(layer, *renderImpl)
+ , render(renderImpl)
+ {
+ for (int i = 0; i < 4; ++i) {
+ textures[i] = context->CreateTexture2D();
+ NVRenderTextureFormats::Enum format = NVRenderTextureFormats::RGBA8;
+ unsigned int data = 0;
+ NVDataRef<QT3DSU8> buffer = toU8DataRef<unsigned int>(data);
+ textures[i]->SetTextureData(buffer, 0, 1, 1, format);
+ }
+ for (int i = 0; i < SShaderDefaultMaterialKeyProperties::ImageMapCount; ++i)
+ dummyImages[i].m_TextureData.m_Texture = textures[i%4];
+ dummyImages[SShaderDefaultMaterialKeyProperties::DiffuseMap1].m_TextureData.
+ m_TextureFlags.SetPreMultiplied(true);
+ dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap2].m_TextureData.
+ m_TextureFlags.SetInvertUVCoords(true);
+ }
+ ~TestParams()
+ {
+ for (NVRenderTexture2D *tex : textures)
+ tex->release();
+ for (SRenderableImage *img : renderableImages)
+ delete img;
+ }
+ void addRenderableImage(ImageMapTypes::Enum type,
+ SShaderDefaultMaterialKeyProperties::ImageMapNames name)
+ {
+ renderableImages.push_back(new SRenderableImage(type, dummyImages[name]));
+ render->DefaultMaterialShaderKeyProperties().m_ImageMaps[name].SetEnabled(shaderkey, true);
+ }
+ void prepare()
+ {
+ for (unsigned int i = 0; i < renderableImages.size(); i++) {
+ if (i == 0)
+ images = renderableImages[0];
+ else {
+ renderableImages[i-1]->m_NextImage = renderableImages[i];
+ }
+
+ }
+ renderable.m_ShaderDescription = shaderkey;
+ renderable.m_FirstImage = images;
+ }
+};
+
+TestKey randomizeTestKey()
+{
+ uint64_t v = (uint64_t(qrand()) << 32 | uint64_t(qrand()))&MAX_TEST_KEY;
+ TestKey key = *reinterpret_cast<TestKey*>(&v);
+ key.clampValues();
+ return key;
+}
+
+
+TestParams *generateTest(qt3ds::render::Qt3DSRendererImpl *renderImpl,
+ NVRenderContext *context, TestKey key)
+{
+ // TODO: light probes
+ TestParams *params = new TestParams(context, renderImpl);
+
+ switch (key.tessellation) {
+ case 1:
+ params->model.m_TessellationMode = TessModeValues::TessLinear;
+ break;
+ case 2:
+ params->model.m_TessellationMode = TessModeValues::TessPhong;
+ break;
+ case 3:
+ params->model.m_TessellationMode = TessModeValues::TessNPatch;
+ break;
+ default:
+ params->model.m_TessellationMode = TessModeValues::NoTess;
+ break;
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_TessellationMode.SetValue(params->shaderkey, params->model.m_TessellationMode);
+
+ switch (key.lighting) {
+ case 1:
+ params->material.m_Lighting = DefaultMaterialLighting::VertexLighting;
+ break;
+ case 2:
+ params->material.m_Lighting = DefaultMaterialLighting::FragmentLighting;
+ break;
+ default:
+ params->material.m_Lighting = DefaultMaterialLighting::NoLighting;
+ break;
+ }
+ if (key.lighting != 0) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_HasLighting.SetValue(params->shaderkey, true);
+ }
+
+ if (key.wireframe && key.tessellation > 0) {
+ params->subset.m_WireframeMode = true;
+ renderImpl->DefaultMaterialShaderKeyProperties().m_WireframeMode.SetValue(
+ params->shaderkey, true);
+ }
+ bool castShadow = false;
+ key.lights = qMin(int(key.lights), int(QT3DS_MAX_NUM_LIGHTS));
+ for (unsigned int i = 0; i < key.lights; ++i) {
+ params->light[i].m_LightType = static_cast<RenderLightTypes::Enum>((i%3)+1);
+ if (params->light[i].m_LightType != RenderLightTypes::Directional) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_LightFlags[i].SetValue(
+ params->shaderkey, true);
+ }
+ if (params->light[i].m_LightType == RenderLightTypes::Area) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_LightAreaFlags[i]
+ .SetValue(params->shaderkey, true);
+ }
+ if (params->light[i].m_LightType != RenderLightTypes::Point) {
+ renderImpl->DefaultMaterialShaderKeyProperties()
+ .m_LightShadowFlags[i]
+ .SetValue(params->shaderkey, castShadow);
+ castShadow = !castShadow;
+ }
+ params->layerData.m_Lights.push_back(&params->light[i]);
+ }
+
+ renderImpl->DefaultMaterialShaderKeyProperties().m_LightCount.SetValue(params->shaderkey,
+ key.lights);
+
+ // shadow lightmap is not used
+ if (key.indirectLightmap) {
+ params->material.m_Lightmaps.m_LightmapIndirect
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapIndirect];
+ params->addRenderableImage(ImageMapTypes::LightmapIndirect,
+ SShaderDefaultMaterialKeyProperties::LightmapIndirect);
+ }
+ if (key.radiosityLightmap) {
+ params->material.m_Lightmaps.m_LightmapRadiosity
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::LightmapRadiosity];
+ params->addRenderableImage(ImageMapTypes::LightmapRadiosity,
+ SShaderDefaultMaterialKeyProperties::LightmapRadiosity);
+ }
+
+ for (unsigned int i = 0; i < key.diffuseMap; ++i) {
+ params->material.m_DiffuseMaps[i]
+ = &params->dummyImages[static_cast<SShaderDefaultMaterialKeyProperties::ImageMapNames>
+ (SShaderDefaultMaterialKeyProperties::DiffuseMap0 + i)];
+ params->addRenderableImage(ImageMapTypes::Diffuse,
+ static_cast<SShaderDefaultMaterialKeyProperties::ImageMapNames>
+ (SShaderDefaultMaterialKeyProperties::DiffuseMap0 + i));
+ }
+
+ if (key.emissiveMap >= 1) {
+ params->material.m_EmissiveMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap];
+ params->addRenderableImage(ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap);
+ }
+ if (key.emissiveMap == 2) {
+ params->material.m_EmissiveMap2
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::EmissiveMap2];
+ params->addRenderableImage(ImageMapTypes::Emissive,
+ SShaderDefaultMaterialKeyProperties::EmissiveMap2);
+ }
+
+ switch (key.specularModel) {
+ case 1:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::KGGX;
+ break;
+ case 2:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::KWard;
+ break;
+ default:
+ params->material.m_SpecularModel = DefaultMaterialSpecularModel::Default;
+ break;
+ }
+
+ if (key.specularMap) {
+ params->material.m_SpecularMap =
+ &params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularAmountMap];
+ params->material.m_SpecularAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::SpecularAmountMap,
+ SShaderDefaultMaterialKeyProperties::SpecularAmountMap);
+ }
+ if (key.specularReflection) {
+ params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularMap].m_MappingMode
+ = ImageMappingModes::Environment;
+ params->material.m_SpecularAmount = 1.0f;
+ params->material.m_SpecularReflection
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::SpecularMap];
+ params->addRenderableImage(ImageMapTypes::Specular,
+ SShaderDefaultMaterialKeyProperties::SpecularMap);
+ }
+ if (key.fresnel)
+ params->material.m_FresnelPower = 1.0f;
+
+ if (key.bumpmapping == 1) {
+ params->material.m_BumpMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::BumpMap];
+ params->material.m_BumpAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Bump, SShaderDefaultMaterialKeyProperties::BumpMap);
+ }
+ if (key.bumpmapping == 2) {
+ params->material.m_NormalMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::NormalMap];
+ params->addRenderableImage(ImageMapTypes::Normal, SShaderDefaultMaterialKeyProperties::NormalMap);
+ }
+
+ if (key.displacementMap) {
+ params->material.m_DisplacementMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::DisplacementMap];
+ params->material.m_DisplaceAmount = 1.0f;
+ params->addRenderableImage(ImageMapTypes::Displacement,
+ SShaderDefaultMaterialKeyProperties::DisplacementMap);
+ }
+
+ if (key.opacityMap) {
+ params->material.m_OpacityMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::OpacityMap];
+ params->material.m_Opacity = 0.5f;
+ params->addRenderableImage(ImageMapTypes::Opacity,
+ SShaderDefaultMaterialKeyProperties::OpacityMap);
+ }
+
+ if (key.translucencyMap) {
+ params->material.m_TranslucencyMap
+ = &params->dummyImages[SShaderDefaultMaterialKeyProperties::TranslucencyMap];
+ params->material.m_TranslucentFalloff = 0.1f;
+ params->addRenderableImage(ImageMapTypes::Translucency,
+ SShaderDefaultMaterialKeyProperties::TranslucencyMap);
+ }
+
+ if (key.ssm) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSM"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssao) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSAO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ if (key.ssdo) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_SSDO"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+
+ if (key.iblLightProbe) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_HasIbl.SetValue(
+ params->shaderkey, true);
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_LIGHT_PROBE"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ if (key.iblfow) {
+ CRegisteredString str(renderImpl->GetQt3DSContext().GetStringTable()
+ .RegisterStr("QT3DS_ENABLE_IBL_FOV"));
+ params->features.push_back(SShaderPreprocessorFeature(str, true));
+ }
+ }
+
+ if (params->material.IsSpecularEnabled()) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_SpecularEnabled.SetValue(
+ params->shaderkey, true);
+ renderImpl->DefaultMaterialShaderKeyProperties().m_SpecularModel.SetSpecularModel(
+ params->shaderkey, params->material.m_SpecularModel);
+ }
+ if (params->material.IsFresnelEnabled()) {
+ renderImpl->DefaultMaterialShaderKeyProperties().m_FresnelEnabled.SetValue(
+ params->shaderkey, true);
+ }
+
+ params->prepare();
+ return params;
+}
+
+
+
+bool Qt3DSRenderTestDefaultMaterialGenerator::run(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ qsrand(QTime::currentTime().msec());
+
+ QVector<TestKey> testKeys;
+
+ testKeys.push_back(TestKey());
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessLinear, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessNPatch, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessPhong, false, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::TessLinear, true, DefaultMaterialLighting::FragmentLighting, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6));
+ // vertex lighting is not supported?
+ //testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::VertexLighting, 6));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 1, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 3, true, true, 0, false, false, 3));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 3, true, true, 0, false, false, 1, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 4, true, true, 0, false, false, 1, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 4, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::KGGX, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 5, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::KWard, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 5, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 6, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 1));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 2));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, false, true));
+ testKeys.push_back(TestKey(TessModeValues::NoTess, false, DefaultMaterialLighting::FragmentLighting, 2, true, true, 0, false, false, 1, 1, DefaultMaterialSpecularModel::Default, true, true, true, 0, true, true, true, true, false, true));
+
+ while (testKeys.size() < 100) {
+ TestKey key = randomizeTestKey();
+ if (!testKeys.contains(key))
+ testKeys.push_back(key);
+ }
+ // generated programs must be unique
+ QVector<NVRenderShaderProgram *> programs;
+ success = initializeQt3DSRenderer(context->format());
+ if (success) {
+ for (TestKey key : testKeys) {
+ qDebug () << "testing key: " << key.toInt();
+ TestParams *params = generateTest(qt3dsRenderer(), context, key);
+
+ qt3dsRenderer()->BeginLayerRender(params->layerData);
+ NVRenderShaderProgram *program
+ = qt3dsRenderer()->GenerateShader(params->renderable,
+ toConstDataRef(params->features.data(),
+ (QT3DSU32)params->features.size()));
+ if (!program) {
+ success = false;
+ } else {
+ if (programs.contains(program)) {
+ qDebug () << "Generated program is not unique vs " << testKeys[programs.indexOf(program)].toString();
+ success = false;
+ }
+ else {
+ programs.push_back(program);
+ }
+ }
+
+ if (!success)
+ qDebug () << "failing test key: " << key.toString();
+
+ qt3dsRenderer()->EndLayerRender();
+ delete params;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h
new file mode 100644
index 0000000..c1464a3
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_DEFAULT_MATERIAL_GENERATOR_H
+#define QT3DS_RENDER_TEST_DEFAULT_MATERIAL_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestDefaultMaterialGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestDefaultMaterialGenerator();
+ ~Qt3DSRenderTestDefaultMaterialGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
new file mode 100644
index 0000000..48346e6
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "Qt3DSRenderTestEffectGenerator.h"
+#include "../Qt3DSRenderTestMathUtil.h"
+#include "render/Qt3DSRenderShaderProgram.h"
+#include "render/Qt3DSRenderContext.h"
+#include "Qt3DSRenderCustomMaterialSystem.h"
+#include "Qt3DSRenderCustomMaterialRenderContext.h"
+#include "Qt3DSRenderCustomMaterialShaderGenerator.h"
+#include "Qt3DSRenderDynamicObjectSystem.h"
+#include "Qt3DSRenderDynamicObjectSystemCommands.h"
+#include "Qt3DSRenderContextCore.h"
+#include "Qt3DSTypes.h"
+#include "Qt3DSRenderRuntimeBinding.h"
+#include "Qt3DSApplication.h"
+#include "Qt3DSInputEngine.h"
+#include "foundation/FileTools.h"
+#include "Qt3DSWindowSystem.h"
+#include "Qt3DSRenderShaderCache.h"
+#include "rendererimpl/Qt3DSRendererImpl.h"
+#include "Qt3DSRenderLight.h"
+#include "Qt3DSRenderUIPLoader.h"
+#include "Qt3DSDMMetaDataTypes.h"
+
+#include <QTime>
+#include <QString>
+#include <QStringList>
+
+#include <string>
+
+using namespace qt3ds::render;
+
+namespace qt3ds {
+namespace render {
+
+Qt3DSRenderTestEffectGenerator::Qt3DSRenderTestEffectGenerator()
+{
+
+}
+
+Qt3DSRenderTestEffectGenerator::~Qt3DSRenderTestEffectGenerator()
+{
+
+}
+
+bool Qt3DSRenderTestEffectGenerator::isSupported(NVRenderContext *context)
+{
+ Q_UNUSED(context);
+ return true;
+}
+
+bool Qt3DSRenderTestEffectGenerator::runPerformance(NVRenderContext *context,
+ userContextData *pContextData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pContextData);
+ return false;
+}
+
+void Qt3DSRenderTestEffectGenerator::cleanup(NVRenderContext *context,
+ userContextData *pUserData)
+{
+ Q_UNUSED(context);
+ Q_UNUSED(pUserData);
+}
+
+bool GenShader(IQt3DSRenderContext &qt3dsContext, SEffect &effect, qt3dsdm::SMetaDataEffect *metaEffect)
+{
+ bool success = true;
+ for (int i = 0; i < metaEffect->m_EffectCommands.size(); i++) {
+ dynamic::SCommand &command = *metaEffect->m_EffectCommands[i];
+ if (command.m_Type == dynamic::CommandTypes::Enum::BindShader) {
+ dynamic::SBindShader *bindShader = static_cast<dynamic::SBindShader *>(&command);
+ NVRenderShaderProgram *theProgram =
+ qt3dsContext.GetDynamicObjectSystem()
+ .GetShaderProgram(bindShader->m_ShaderPath, bindShader->m_ShaderDefine,
+ TShaderFeatureSet(), dynamic::SDynamicShaderProgramFlags())
+ .first;
+ if (!theProgram)
+ success = false;
+ }
+ }
+ return success;
+}
+
+bool Qt3DSRenderTestEffectGenerator::run(NVRenderContext *context, userContextData *pUserData)
+{
+ Q_UNUSED(pUserData);
+ bool success = true;
+
+ QStringList effectFiles;
+ effectFiles.append("Desaturate.effect");
+ effectFiles.append("Gaussian Blur.effect");
+ effectFiles.append("Sepia.effect");
+ effectFiles.append("Bloom.effect");
+
+ for (QString effectName : effectFiles) {
+ QString qfile = "qrc:/";
+ qfile.append(effectName);
+ QByteArray data = qfile.toLatin1();
+ const char *cname = data.data();
+ CRegisteredString name = context->GetStringTable().RegisterStr(cname);
+
+ metadata()->LoadEffectXMLFile("Effect", "", effectName.toLatin1().data(), cname);
+ Option<qt3dsdm::SMetaDataEffect> metaEffect =
+ metadata()->GetEffectMetaDataBySourcePath(cname);
+
+ if (metaEffect.hasValue()) {
+ qt3ds::render::IUIPLoader::CreateEffectClassFromMetaEffect(
+ name, context->GetFoundation(),
+ qt3dsRenderer()->GetQt3DSContext().GetEffectSystem(), *metaEffect,
+ context->GetStringTable());
+
+ SEffect *effect = qt3dsRenderer()->GetQt3DSContext().GetEffectSystem()
+ .CreateEffectInstance(name, qt3dsRenderer()->GetContext().GetAllocator());
+
+ success &= GenShader(qt3dsRenderer()->GetQt3DSContext(), *effect, &metaEffect.getValue());
+ if (!success)
+ qDebug () << "failed effect: " << effectName;
+ delete effect;
+ }
+ }
+
+ return success;
+}
+
+} // render
+} // qt3ds
diff --git a/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h
new file mode 100644
index 0000000..4e26cf3
--- /dev/null
+++ b/tests/auto/runtime/shadergenerator/Qt3DSRenderTestEffectGenerator.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DS_RENDER_TEST_EFFECT_GENERATOR_H
+#define QT3DS_RENDER_TEST_EFFECT_GENERATOR_H
+
+#include "../Qt3DSRenderTestBase.h"
+
+namespace qt3ds {
+namespace render {
+
+class Qt3DSRenderTestEffectGenerator : public NVRenderTestBase
+{
+public:
+ Qt3DSRenderTestEffectGenerator();
+ ~Qt3DSRenderTestEffectGenerator();
+
+ bool isSupported(NVRenderContext *context);
+ bool run(NVRenderContext *context, userContextData *pUserData);
+ bool runPerformance(NVRenderContext *context, userContextData *pContextData);
+ void cleanup(NVRenderContext *context, userContextData *pUserData);
+
+private:
+
+};
+
+} // render
+} // qt3ds
+
+#endif
diff --git a/tests/auto/runtime/tst_qt3dsruntime.cpp b/tests/auto/runtime/tst_qt3dsruntime.cpp
new file mode 100644
index 0000000..763529c
--- /dev/null
+++ b/tests/auto/runtime/tst_qt3dsruntime.cpp
@@ -0,0 +1,727 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "tst_qt3dsruntime.h"
+
+#include "render/Qt3DSRenderContext.h"
+#include "foundation/TrackingAllocator.h"
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/StringTable.h"
+#include "foundation/Qt3DSMat44.h"
+
+#include "base/Qt3DSRenderTestClear.h"
+#include "base/Qt3DSRenderTestPrimitives.h"
+#include "base/Qt3DSRenderTestConstantBuffer.h"
+#include "base/Qt3DSRenderTestBackendQuery.h"
+#include "base/Qt3DSRenderTestTimerQuery.h"
+#include "base/Qt3DSRenderTestTexture2D.h"
+#include "base/Qt3DSRenderTestAtomicCounterBuffer.h"
+#include "base/Qt3DSRenderTestDrawIndirectBuffer.h"
+#include "base/Qt3DSRenderTestAttribBuffers.h"
+#include "base/Qt3DSRenderTestProgramPipeline.h"
+#include "fbo/Qt3DSRenderTestFboMsaa.h"
+#include "geometry/Qt3DSRenderTestTessellation.h"
+#include "geometry/Qt3DSRenderTestGeometryShader.h"
+#include "geometry/Qt3DSRenderTestOcclusionQuery.h"
+#include "compute/Qt3DSRenderTestComputeShader.h"
+#include "shadergenerator/Qt3DSRenderTestDefaultMaterialGenerator.h"
+#include "shadergenerator/Qt3DSRenderTestCustomMaterialGenerator.h"
+#include "shadergenerator/Qt3DSRenderTestEffectGenerator.h"
+
+#include <QImage>
+#include <QOpenGLContext>
+#include <QOffscreenSurface>
+#include <QOpenGLFramebufferObject>
+#include <QOpenGLFramebufferObjectFormat>
+
+using namespace std;
+using namespace qt3ds;
+using namespace qt3ds::render;
+using namespace qt3ds::foundation;
+
+extern "C" {
+bool InitializeGL();
+}
+
+// Enable this to dump the test output into a log.txt file
+//#define DUMP_LOGFILE
+
+#ifndef EA_PLATFORM_WINDOWS
+
+#ifndef EASTL_DEBUG_BREAK
+void EASTL_DEBUG_BREAK()
+{
+ return;
+}
+#endif
+
+namespace qt3ds {
+void NVAssert(const char *exp, const char *file, int line, bool *ignore)
+{
+ *ignore = true;
+ QString message = QString("failed: %1, file %2, line %3\n")
+ .arg(exp).arg(file).arg(line);
+ QFAIL(message.toLatin1().constData());
+}
+}
+#endif
+
+void messageOutput(QtMsgType type, const QMessageLogContext &context,
+ const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg: {
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << msg;
+ }
+ file.close();
+#endif
+ } break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_qt3dsruntime::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ QTextStream stream(&file);
+ stream << "Log file: " << QTime::currentTime().toString() << "\n";
+ }
+ file.close();
+#endif
+}
+
+QSurfaceFormat makeFormat(int major, int minor, bool gles = false, bool coreProfile = true)
+{
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(major, minor);
+ if (coreProfile)
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ else
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ if (gles)
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+ return format;
+}
+
+bool tst_qt3dsruntime::init(QSurfaceFormat format)
+{
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return false;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+ m_stringTable = &IStringTable::CreateStringTable(*m_allocator);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, *m_stringTable, format);
+ return true;
+}
+
+bool tst_qt3dsruntime::init()
+{
+#if defined(QT_OPENGL_ES_2)
+ return init(makeFormat(2, 0, true, false));
+#elif defined(Q_OS_ANDROID) || defined(QT_OPENGL_ES_3)
+ return init(makeFormat(3, 2, true, false));
+#else
+ return init(makeFormat(4, 3));
+#endif
+}
+
+bool tst_qt3dsruntime::executeTest(NVRenderTestBase *curTest,
+ const QString &testName,
+ bool performPixelTest)
+{
+ bool success = true;
+ int width = 640;
+ int height = 480;
+ userContextData userData = { (unsigned int)width, (unsigned int)height };
+
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(QSize(width, height), fboFormat);
+
+ m_renderContext->SetDefaultRenderTarget(fbo->handle());
+ m_renderContext->SetDefaultDepthBufferBitCount(m_glContext->format().depthBufferSize());
+ m_renderContext->SetViewport(NVRenderRect(0, 0, userData.winWidth, userData.winHeight));
+
+ success = curTest->run(m_renderContext, &userData);
+
+ if (performPixelTest) {
+ QImage image = fbo->toImage();
+ QImage refImage(QString(":/images/%1.png").arg(testName));
+ refImage = refImage.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ if (!refImage.isNull()) {
+ bool pixelTest = image == refImage;
+ success &= pixelTest;
+ if (!pixelTest)
+ image.save(QString("%1_failed.png").arg(testName));
+ }
+ }
+
+ curTest->cleanup(m_renderContext, &userData);
+
+ return success;
+}
+
+void tst_qt3dsruntime::testNVRenderTestClear()
+{
+ init();
+ NVRenderTestClear *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestClear);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestClear");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestPrimitives()
+{
+ init();
+ NVRenderTestPrimitives *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestPrimitives);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestPrimitives");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestConstantBuffer()
+{
+ init();
+ NVRenderTestConstantBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestConstantBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestConstantBuffer");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestBackendQuery()
+{
+ init();
+ NVRenderTestBackendQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestBackendQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestBackendQuery", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTimerQuery()
+{
+ init();
+ NVRenderTestTimerQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTimerQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestTimerQuery");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestFboMsaa()
+{
+ init();
+ NVRenderTestFboMsaa *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestFboMsaa);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestFboMsaa", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTessellation()
+{
+ init();
+ NVRenderTestTessellation *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTessellation);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestTessellation");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestGeometryShader()
+{
+ init();
+ NVRenderTestGeometryShader *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestGeometryShader);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestGeometryShader");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestComputeShader()
+{
+ init();
+ NVRenderTestComputeShader *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestComputeShader);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestComputeShader", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestOcclusionQuery()
+{
+ init();
+ NVRenderTestOcclusionQuery *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestOcclusionQuery);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestOcclusionQuery", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestTexture2D()
+{
+ init();
+ NVRenderTestTexture2D *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestTexture2D);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestTexture2D", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestAtomicCounterBuffer()
+{
+ init();
+ NVRenderTestAtomicCounterBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestAtomicCounterBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ bool success = executeTest(test, "NVRenderTestAtomicCounterBuffer");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestDrawIndirectBuffer()
+{
+ init();
+ NVRenderTestDrawIndirectBuffer *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestDrawIndirectBuffer);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestDrawIndirectBuffer", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestAttribBuffers()
+{
+ init();
+ NVRenderTestAttribBuffers *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestAttribBuffers);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestAttribBuffers", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testNVRenderTestProgramPipeline()
+{
+ init();
+ NVRenderTestProgramPipeline *test =
+ QT3DS_NEW(m_foundation->getAllocator(), NVRenderTestProgramPipeline);
+ if (!test->isSupported(m_renderContext)) {
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ QSKIP("not supported");
+ }
+ // TODO: Fix BOUL-332 to re-enable this pixel test
+ bool success = executeTest(test, "NVRenderTestProgramPipeline", false);
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+#if defined(QT_OPENGL_ES_2)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_200es()
+{
+ if (init(makeFormat(2, 0, true, false))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_200es()
+{
+ runCustomShaderGeneratorTest(makeFormat(2, 0, true, false));
+ cleanup();
+}
+#endif
+
+#if defined(QT_OPENGL_ES_3)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_300es()
+{
+ if (init(makeFormat(3, 0, true, false))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_300es()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 0, true, false));
+ cleanup();
+}
+
+#if defined(QT_FEATURE_opengles31)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_310es()
+{
+ if (init(makeFormat(3, 1, true, false))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_310es()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 1, true, false));
+ cleanup();
+}
+#endif
+#if defined(QT_FEATURE_opengles32)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320es()
+{
+ if (init(makeFormat(3, 1, true, false))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_320es()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 1, true, false));
+ cleanup();
+}
+
+#endif
+#endif
+
+#if defined(QT_OPENGL_DYNAMIC)
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_300()
+{
+ QSKIP("OpenGL 3.0 is not supported");
+ if (init(makeFormat(3, 0))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_310()
+{
+ if (init(makeFormat(3, 1))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_320()
+{
+ if (init(makeFormat(3, 2))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_330()
+{
+ if (init(makeFormat(3, 3))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_400()
+{
+ if (init(makeFormat(4, 0))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_410()
+{
+ if (init(makeFormat(4, 1))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_420()
+{
+ if (init(makeFormat(4, 2))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderDefaultShaderGenerator_430()
+{
+ if (init(makeFormat(4, 3))) {
+ runDefaultShaderGeneratorTest();
+ cleanup();
+ }
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_300()
+{
+ QSKIP("OpenGL 3.0 is not supported");
+ runCustomShaderGeneratorTest(makeFormat(3, 0));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_310()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 1));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_320()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 2));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_330()
+{
+ runCustomShaderGeneratorTest(makeFormat(3, 3));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_400()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 0));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_410()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 1));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_420()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 2));
+}
+
+void tst_qt3dsruntime::testRenderCustomShaderGenerator_430()
+{
+ runCustomShaderGeneratorTest(makeFormat(4, 3));
+}
+
+#endif
+
+void tst_qt3dsruntime::runDefaultShaderGeneratorTest()
+{
+ Qt3DSRenderTestDefaultMaterialGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestDefaultMaterialGenerator);
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ bool success = executeTest(test, "Qt3DSRenderTestDefaultMaterialGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+}
+
+void tst_qt3dsruntime::runCustomShaderGeneratorTest(QSurfaceFormat format)
+{
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+
+ Qt3DSRenderTestCustomMaterialGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestCustomMaterialGenerator);
+
+ test->initializeQt3DSRenderer(format);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, test->qt3dsRenderer()->GetContext()
+ .GetStringTable(), format);
+
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ success = executeTest(test, "Qt3DSRenderTestCusromMaterialGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::testRenderEffectGenerator()
+{
+ QSurfaceFormat format = makeFormat(4, 3);
+ m_glContext = new QT_PREPEND_NAMESPACE(QOpenGLContext)(this);
+ m_glContext->setFormat(format);
+ bool success = m_glContext->create();
+ if (!success)
+ return;
+
+ m_glSurface = new QOffscreenSurface;
+ m_glSurface->setFormat(format);
+ m_glSurface->create();
+ m_glContext->makeCurrent(m_glSurface);
+
+ m_allocator = new CAllocator;
+ m_foundation = NVCreateFoundation(QT3DS_FOUNDATION_VERSION, *m_allocator);
+
+ Qt3DSRenderTestEffectGenerator *test =
+ QT3DS_NEW(m_foundation->getAllocator(), Qt3DSRenderTestEffectGenerator);
+
+ test->initializeQt3DSRenderer(format);
+ m_renderContext = &NVRenderContext::CreateGL(*m_foundation, test->qt3dsRenderer()->GetContext()
+ .GetStringTable(), format);
+
+ if (!test->isSupported(m_renderContext))
+ QSKIP("not supported");
+ success = executeTest(test, "Qt3DSRenderTestEffectGenerator");
+ QT3DS_FREE(m_foundation->getAllocator(), test);
+ test = 0;
+ QVERIFY(success);
+ cleanup();
+}
+
+void tst_qt3dsruntime::cleanup()
+{
+ if (m_renderContext)
+ m_renderContext->release();
+ if (m_foundation)
+ m_foundation->release();
+
+ m_renderContext = 0;
+ m_stringTable = 0;
+ m_foundation = 0;
+
+ delete m_allocator;
+ m_allocator = 0;
+
+ m_glSurface->destroy();
+ delete m_glSurface;
+ m_glSurface = 0;
+
+ delete m_glContext;
+ m_glContext = 0;
+}
+
+QTEST_MAIN(tst_qt3dsruntime)
diff --git a/tests/auto/runtime/tst_qt3dsruntime.h b/tests/auto/runtime/tst_qt3dsruntime.h
new file mode 100644
index 0000000..1f5b943
--- /dev/null
+++ b/tests/auto/runtime/tst_qt3dsruntime.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QT3DSRUNTIME
+#define TST_QT3DSRUNTIME
+
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+
+namespace qt3ds {
+class NVFoundation;
+namespace foundation {
+class CAllocator;
+class IStringTable;
+}
+namespace render {
+class NVRenderContext;
+class NVRenderTestBase;
+}
+}
+
+QT_BEGIN_NAMESPACE
+class QOpenGLContext;
+class QOffscreenSurface;
+QT_END_NAMESPACE
+
+class tst_qt3dsruntime : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qt3dsruntime()
+ : m_allocator(0)
+ , m_foundation(0)
+ , m_stringTable(0)
+ , m_renderContext(0)
+ , m_glContext(0)
+ , m_glSurface(0)
+ {
+ }
+
+private Q_SLOTS:
+ void initTestCase();
+
+ void testNVRenderTestClear();
+ void testNVRenderTestPrimitives();
+ void testNVRenderTestConstantBuffer();
+ void testNVRenderTestBackendQuery();
+ void testNVRenderTestTimerQuery();
+ void testNVRenderTestFboMsaa();
+ void testNVRenderTestTessellation();
+ void testNVRenderTestGeometryShader();
+ void testNVRenderTestComputeShader();
+ void testNVRenderTestOcclusionQuery();
+ void testNVRenderTestTexture2D();
+ void testNVRenderTestAtomicCounterBuffer();
+ void testNVRenderTestDrawIndirectBuffer();
+ void testNVRenderTestAttribBuffers();
+ void testNVRenderTestProgramPipeline();
+
+ void testRenderEffectGenerator();
+
+#if defined(QT_OPENGL_ES_2)
+ void testRenderDefaultShaderGenerator_200es();
+ void testRenderCustomShaderGenerator_200es();
+#endif
+#if defined(QT_OPENGL_ES_3)
+ void testRenderDefaultShaderGenerator_300es();
+ void testRenderCustomShaderGenerator_300es();
+#if defined(QT_FEATURE_opengles31)
+ void testRenderDefaultShaderGenerator_310es();
+ void testRenderCustomShaderGenerator_310es();
+#endif
+#if defined(QT_FEATURE_opengles32)
+ void testRenderDefaultShaderGenerator_320es();
+ void testRenderCustomShaderGenerator_320es();
+#endif
+#endif
+
+#if defined(QT_OPENGL_DYNAMIC)
+ void testRenderDefaultShaderGenerator_300();
+ void testRenderDefaultShaderGenerator_310();
+ void testRenderDefaultShaderGenerator_320();
+ void testRenderDefaultShaderGenerator_330();
+ void testRenderDefaultShaderGenerator_400();
+ void testRenderDefaultShaderGenerator_410();
+ void testRenderDefaultShaderGenerator_420();
+ void testRenderDefaultShaderGenerator_430();
+
+ void testRenderCustomShaderGenerator_300();
+ void testRenderCustomShaderGenerator_310();
+ void testRenderCustomShaderGenerator_320();
+ void testRenderCustomShaderGenerator_330();
+ void testRenderCustomShaderGenerator_400();
+ void testRenderCustomShaderGenerator_410();
+ void testRenderCustomShaderGenerator_420();
+ void testRenderCustomShaderGenerator_430();
+#endif
+
+
+
+private:
+ bool executeTest(qt3ds::render::NVRenderTestBase *curTest,
+ const QString &testName, bool peformPixelTest = true);
+ bool init(QSurfaceFormat format);
+ bool init();
+ void runDefaultShaderGeneratorTest();
+ void runCustomShaderGeneratorTest(QSurfaceFormat format);
+ void cleanup();
+
+ qt3ds::foundation::CAllocator *m_allocator;
+ qt3ds::NVFoundation *m_foundation;
+ qt3ds::foundation::IStringTable *m_stringTable;
+ qt3ds::render::NVRenderContext *m_renderContext;
+ QOpenGLContext *m_glContext;
+ QOffscreenSurface *m_glSurface;
+};
+
+#endif // TST_QT3DSRUNTIME
diff --git a/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro b/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro
new file mode 100644
index 0000000..7da6bf7
--- /dev/null
+++ b/tests/auto/studio3d/q3dssurfaceviewer/q3dssurfaceviewer.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+CONFIG += testcase
+
+TARGET = tst_q3dssurfaceviewer
+
+QT += testlib studio3d
+
+SOURCES += tst_q3dssurfaceviewer.cpp
+
+RESOURCES += ../shared/shared_presentations.qrc
diff --git a/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
new file mode 100644
index 0000000..786ef3a
--- /dev/null
+++ b/tests/auto/studio3d/q3dssurfaceviewer/tst_q3dssurfaceviewer.cpp
@@ -0,0 +1,1516 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtStudio3D/q3dssurfaceviewer.h>
+#include <QtStudio3D/q3dsviewersettings.h>
+#include <QtStudio3D/q3dspresentation.h>
+#include <QtStudio3D/q3dssceneelement.h>
+#include <QtStudio3D/q3dselement.h>
+#include <QtStudio3D/q3dsdatainput.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qoffscreensurface.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qopenglframebufferobject.h>
+#include <QtGui/qevent.h>
+#include <QtCore/qurl.h>
+#include <QtCore/qfile.h>
+#include "../shared/shared_presentations.h"
+
+class tst_Q3DSSurfaceViewer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_Q3DSSurfaceViewer();
+ ~tst_Q3DSSurfaceViewer() {}
+
+private slots:
+ void initTestCase();
+ void init();
+ void cleanup();
+
+ void testBasics_data();
+ void testBasics();
+ void testSourceChange_data();
+ void testSourceChange();
+ void testSizeChange_data();
+ void testSizeChange();
+ void testUpdateInterval_data();
+ void testUpdateInterval();
+ void testMultiple_data();
+ void testMultiple();
+ void testGrab_data();
+ void testGrab();
+ void testReset_data();
+ void testReset();
+ void testSettings_data();
+ void testSettings();
+ void testPresentation_data();
+ void testPresentation();
+ void testPresentationActivation_data();
+ void testPresentationActivation();
+ void testSceneElement_data();
+ void testSceneElement();
+ void testElement_data();
+ void testElement();
+ void testMouseInput_data();
+ void testMouseInput();
+ void testDataInput_data();
+ void testDataInput();
+
+private:
+ QWindow *createWindow(const QSize &size);
+ QOffscreenSurface *createOffscreen();
+ QOpenGLFramebufferObject *createFbo(const QSize &size);
+
+ // Created viewers are returned via *&viewer parameter rather than return value, so that we can
+ // use QCOMPARE and QVERIFY inside these functions (they require void return value).
+ void createViewer(Q3DSSurfaceViewer *&viewer, QSurface *surface, const QUrl &url,
+ bool autoSize, const QSize &size, int updateInterval, int fboId);
+ void createWindowAndViewer(Q3DSSurfaceViewer *&viewer, const QUrl &url = RED,
+ bool autoSize = true, const QSize &size = QSize(),
+ int updateInterval = 0);
+ void createOffscreenAndViewer(Q3DSSurfaceViewer *&viewer, const QUrl &url = RED,
+ const QSize &size = QSize(), int updateInterval = 0);
+ void checkPixel(Q3DSSurfaceViewer *viewer, const QColor &color,
+ const QPoint &pixel = QPoint(50, 50));
+
+ QWindow *m_window;
+ QOffscreenSurface *m_surface;
+ Q3DSSurfaceViewer *m_viewer;
+ QSurfaceFormat m_format;
+ QOpenGLContext *m_context;
+ QOpenGLFramebufferObject *m_fbo;
+};
+
+tst_Q3DSSurfaceViewer::tst_Q3DSSurfaceViewer()
+ : m_window(nullptr)
+ , m_surface(nullptr)
+ , m_viewer(nullptr)
+ , m_context(nullptr)
+ , m_fbo(nullptr)
+{
+}
+
+//#define DUMP_LOGFILE // Uncomment log Qt 3D Studio internal messages to log.txt file
+void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ // case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg: {
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
+ QTextStream stream(&file);
+ stream << msg << "\n";
+ }
+ file.close();
+#endif
+ } break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_Q3DSSurfaceViewer::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+#ifdef DUMP_LOGFILE
+ QFile file("log.txt");
+ if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
+ QTextStream stream(&file);
+ stream << "Log file: " << QTime::currentTime().toString() << "\n";
+ }
+ file.close();
+#endif
+
+ QWindow *dummy = createWindow(QSize(100, 100));
+ m_format = dummy->format();
+ qDebug() << m_format;
+ delete dummy;
+}
+
+void tst_Q3DSSurfaceViewer::init()
+{
+ m_context = new QOpenGLContext();
+ m_context->setFormat(m_format);
+ m_context->create();
+}
+
+void tst_Q3DSSurfaceViewer::cleanup()
+{
+ if (m_window)
+ m_window->close();
+
+ delete m_viewer;
+ m_viewer = nullptr;
+
+ delete m_window;
+ m_window = nullptr;
+
+ delete m_surface;
+ m_surface = nullptr;
+
+ delete m_fbo;
+ m_fbo = nullptr;
+
+ delete m_context;
+ m_context = nullptr;
+}
+
+QWindow *tst_Q3DSSurfaceViewer::createWindow(const QSize &size)
+{
+ QWindow *window = new QWindow();
+
+ window->resize(size);
+ window->setSurfaceType(QSurface::OpenGLSurface);
+ window->setFormat(m_format);
+ window->setTitle(QStringLiteral("Q3DSSurfaceViewer test window"));
+ window->create();
+
+ return window;
+}
+
+QOffscreenSurface *tst_Q3DSSurfaceViewer::createOffscreen()
+{
+ QOffscreenSurface *surface = new QOffscreenSurface();
+ surface->setFormat(m_format);
+ surface->create();
+
+ return surface;
+}
+
+QOpenGLFramebufferObject *tst_Q3DSSurfaceViewer::createFbo(const QSize &size)
+{
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ return new QOpenGLFramebufferObject(size, fboFormat);
+}
+
+void tst_Q3DSSurfaceViewer::createViewer(Q3DSSurfaceViewer *&viewer, QSurface *surface,
+ const QUrl &url, bool autoSize, const QSize &size,
+ int updateInterval, int fboId)
+{
+ viewer = new Q3DSSurfaceViewer();
+ QSignalSpy spy(viewer, &Q3DSSurfaceViewer::runningChanged);
+
+ viewer->presentation()->setSource(url);
+ QCOMPARE(viewer->presentation()->source(), url);
+
+ QVERIFY(spy.isValid());
+ QCOMPARE(spy.count(), 0);
+
+ viewer->setAutoSize(autoSize);
+ if (!autoSize)
+ viewer->setSize(size);
+ viewer->setUpdateInterval(updateInterval);
+
+ QVERIFY(viewer->create(surface, m_context, fboId));
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(viewer->isRunning());
+
+ QVERIFY(viewer->fboId() == fboId);
+ QVERIFY(viewer->surface() == surface);
+ QVERIFY(viewer->context() == m_context);
+}
+
+void tst_Q3DSSurfaceViewer::createWindowAndViewer(Q3DSSurfaceViewer *&viewer,
+ const QUrl &url, bool autoSize,
+ const QSize &size, int updateInterval)
+{
+ QSize actualSize = size;
+ if (actualSize.isEmpty())
+ actualSize = QSize(300, 200);
+
+ m_window = createWindow(actualSize);
+
+ createViewer(viewer, m_window, url, autoSize, actualSize, updateInterval, 0);
+
+ m_window->show();
+ QGuiApplication::processEvents();
+}
+
+void tst_Q3DSSurfaceViewer::createOffscreenAndViewer(Q3DSSurfaceViewer *&viewer,
+ const QUrl &url, const QSize &size,
+ int updateInterval)
+{
+ QSize actualSize = size;
+ if (actualSize.isEmpty())
+ actualSize = QSize(300, 200);
+
+ m_surface = createOffscreen();
+ m_context->makeCurrent(m_surface);
+ m_fbo = createFbo(actualSize);
+
+ createViewer(viewer, m_surface, url, false, actualSize, updateInterval, m_fbo->handle());
+}
+
+void tst_Q3DSSurfaceViewer::checkPixel(Q3DSSurfaceViewer *viewer, const QColor &color,
+ const QPoint &pixel)
+{
+ // Grab operation is potentially costly, so retry only every second instead of using
+ // QTRY_COMPARE which would try it every 50ms. We also want to wait first as it takes some time
+ // for the presentation to be displayed.
+ QColor grabColor;
+ for (int i = 0; i < 20; i++) {
+ // Note: If checkpixel is ever changed to not have this wait, some
+ // QGuiApplication::processEvents() calls may be necessary in various test cases to
+ // ensure expected signaling order.
+ QTest::qWait(1000);
+ QImage image = viewer->grab(QRect(pixel, QSize(1, 1)));
+ grabColor = QColor(image.pixel(0, 0));
+ if (grabColor == color)
+ break;
+ }
+ QCOMPARE(grabColor, color);
+}
+
+void tst_Q3DSSurfaceViewer::testBasics_data()
+{
+ QTest::addColumn<bool>("isWindow");
+ QTest::newRow("window") << true;
+ QTest::newRow("offscreen") << false;
+}
+
+void tst_Q3DSSurfaceViewer::testBasics()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer, &Q3DSSurfaceViewer::runningChanged);
+ QVERIFY(spy.isValid());
+
+ checkPixel(m_viewer, Qt::red);
+
+ m_viewer->destroy();
+
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(!m_viewer->isRunning());
+}
+
+void tst_Q3DSSurfaceViewer::testSourceChange_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSourceChange()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ QSignalSpy spy(m_viewer->presentation(), &Q3DSPresentation::sourceChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Different source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Reset same source
+ m_viewer->presentation()->setSource(BLUE);
+ QCOMPARE(spy.count(), 1);
+ QVERIFY(m_viewer->presentation()->source() == BLUE);
+
+ checkPixel(m_viewer, Qt::blue);
+
+ // Different source again
+ m_viewer->presentation()->setSource(RED);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->presentation()->source() == RED);
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSSurfaceViewer::testSizeChange_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSizeChange()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow) {
+ createWindowAndViewer(m_viewer, MIXED, true, QSize(600, 600));
+ } else {
+ // Changing size for offscreen surface means recreating the fbo. There's no guarantee
+ // we can get the same fbo id if we do that, so we would have to reinitialize anyway
+ QSKIP("Skipping size change testing for offscreen surfaces");
+ }
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spy1(m_viewer, &Q3DSSurfaceViewer::sizeChanged);
+ QVERIFY(spy1.isValid());
+ QSignalSpy spy2(m_viewer, &Q3DSSurfaceViewer::autoSizeChanged);
+ QVERIFY(spy2.isValid());
+
+ QPoint leftPoint(m_viewer->size().width() * 11 / 24, m_viewer->size().height() / 2);
+ QPoint rightPoint(m_viewer->size().width() * 13 / 24, m_viewer->size().height() / 2);
+
+ // MIXED presentation has left side blue, right side red
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_window->resize(QSize(800, 800));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 1);
+
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::blue, rightPoint);
+
+ m_window->resize(QSize(400, 400));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 2);
+
+ checkPixel(m_viewer, Qt::red, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_viewer->setAutoSize(false);
+ QCOMPARE(spy2.count(), 1);
+
+ // Size should not change since autosize is no longer on
+ m_window->resize(QSize(600, 600));
+ QGuiApplication::processEvents();
+ QCOMPARE(spy1.count(), 2);
+
+ checkPixel(m_viewer, Qt::red, leftPoint);
+ checkPixel(m_viewer, Qt::red, rightPoint);
+
+ m_viewer->setSize(QSize(700, 700));
+ QCOMPARE(spy1.count(), 3);
+
+ checkPixel(m_viewer, Qt::blue, leftPoint);
+ checkPixel(m_viewer, Qt::blue, rightPoint);
+}
+
+void tst_Q3DSSurfaceViewer::testUpdateInterval_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testUpdateInterval()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, ANIMATION);
+ else
+ createOffscreenAndViewer(m_viewer, ANIMATION);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spy(m_viewer, &Q3DSSurfaceViewer::updateIntervalChanged);
+ QVERIFY(spy.isValid());
+ QVERIFY(m_viewer->updateInterval() == 0);
+
+ checkPixel(m_viewer, Qt::black);
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ }
+ {
+ m_viewer->setUpdateInterval(100000);
+ QVERIFY(m_viewer->updateInterval() == 100000);
+ QCOMPARE(spy.count(), 1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+ {
+ m_viewer->setUpdateInterval(20);
+ QCOMPARE(spy.count(), 2);
+ QVERIFY(m_viewer->updateInterval() == 20);
+
+ // Non-zero interval short enough to see animation
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+ {
+ m_viewer->setUpdateInterval(-1);
+ QCOMPARE(spy.count(), 3);
+ QVERIFY(m_viewer->updateInterval() == -1);
+ // Can't test if animation actually stopped, as grabbing the viewer forces update on it
+ }
+}
+
+void tst_Q3DSSurfaceViewer::testMultiple_data()
+{
+ QTest::addColumn<int>("windowCount");
+ QTest::addColumn<int>("offscreenCount");
+ QTest::newRow("windows") << 2 << 0;
+ QTest::newRow("offscreens") << 0 << 2;
+ QTest::newRow("mixed") << 1 << 1;
+}
+
+void tst_Q3DSSurfaceViewer::testMultiple()
+{
+ QFETCH(int, windowCount);
+ QFETCH(int, offscreenCount);
+
+ QVector<QWindow *> windows;
+ QVector<QOffscreenSurface *> surfaces;
+ QVector<Q3DSSurfaceViewer *> viewers;
+ QVector<QOpenGLFramebufferObject *> fbos;
+
+ int viewerCount = windowCount + offscreenCount;
+ windows.resize(windowCount);
+ surfaces.resize(offscreenCount);
+ fbos.resize(offscreenCount);
+ viewers.resize(viewerCount);
+
+ QSize size(200, 150);
+ QUrl url;
+ for (int i = 0; i < windowCount; i++) {
+ windows[i] = createWindow(size);
+ if (i % 2)
+ url = RED;
+ else
+ url = BLUE;
+ createViewer(viewers[i], windows[i], url, true, size, 0, 0);
+ windows[i]->setPosition(10 + i * 50, 10 + i * 50);
+ windows[i]->show();
+ QGuiApplication::processEvents();
+ }
+ for (int i = 0; i < offscreenCount; i++) {
+ surfaces[i] = createOffscreen();
+ m_context->makeCurrent(surfaces[i]);
+ fbos[i] = createFbo(size);
+ if ((i + windowCount) % 2)
+ url = RED;
+ else
+ url = BLUE;
+ createViewer(viewers[i + windowCount], surfaces[i], url, false, size, 0,
+ fbos[i]->handle());
+ }
+
+ for (int i = 0; i < viewerCount; i++) {
+ if (i % 2)
+ checkPixel(viewers[i], Qt::red);
+ else
+ checkPixel(viewers[i], Qt::blue);
+ }
+
+ for (QWindow *w : windows) {
+ w->close();
+ delete w;
+ }
+ windows.clear();
+
+ for (QOffscreenSurface *s : surfaces)
+ delete s;
+ surfaces.clear();
+
+ for (Q3DSSurfaceViewer *v : viewers)
+ delete v;
+ viewers.clear();
+
+ for (QOpenGLFramebufferObject *f : fbos)
+ delete f;
+ fbos.clear();
+}
+
+void tst_Q3DSSurfaceViewer::testGrab_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testGrab()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MIXED_VERTICAL);
+ else
+ createOffscreenAndViewer(m_viewer, MIXED_VERTICAL);
+
+ // Single pixels
+ int w = m_viewer->size().width();
+ int h = m_viewer->size().height();
+
+ checkPixel(m_viewer, Qt::blue, QPoint(w / 2, h / 4));
+ checkPixel(m_viewer, Qt::red, QPoint(w / 2, 3 * h / 4));
+
+ checkPixel(m_viewer, Qt::blue, QPoint(0, 0));
+ checkPixel(m_viewer, Qt::blue, QPoint(w - 1, 0));
+ checkPixel(m_viewer, Qt::red, QPoint(0, h - 1));
+ checkPixel(m_viewer, Qt::red, QPoint(w - 1, h - 1));
+
+ // Full buffer
+ QImage img = m_viewer->grab();
+ QColor grabColor1 = img.pixel(w / 2, h / 4);
+ QColor grabColor2 = img.pixel(w / 2, 3 * h / 4);
+ QCOMPARE(grabColor1, QColor(Qt::blue));
+ QCOMPARE(grabColor2, QColor(Qt::red));
+
+ // Partial buffer
+ img = m_viewer->grab(QRect(w / 3, h / 3, w / 2, h / 2));
+ grabColor1 = img.pixel(0, 0);
+ grabColor2 = img.pixel(w / 2 - 1, h / 2 - 1);
+ QCOMPARE(grabColor1, QColor(Qt::blue));
+ QCOMPARE(grabColor2, QColor(Qt::red));
+}
+
+void tst_Q3DSSurfaceViewer::testReset_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testReset()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, RED);
+ else
+ createOffscreenAndViewer(m_viewer, RED);
+
+ checkPixel(m_viewer, Qt::red);
+
+ m_viewer->presentation()->setAttribute(QStringLiteral("Scene.Layer.Rectangle.Material"),
+ QStringLiteral("diffuse.r"), QVariant(0.0));
+ m_viewer->presentation()->setAttribute(QStringLiteral("Scene.Layer.Rectangle.Material"),
+ QStringLiteral("diffuse.b"), QVariant(1.0));
+ checkPixel(m_viewer, Qt::blue);
+
+ // Note: reset() is private method now, instead can reload presentation by switching sources
+ // m_viewer->reset();
+ m_viewer->presentation()->setSource(ANIMATION);
+ m_viewer->presentation()->setSource(RED);
+
+ checkPixel(m_viewer, Qt::red);
+}
+
+void tst_Q3DSSurfaceViewer::testSettings_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSettings()
+{
+ QFETCH(bool, isWindow);
+
+ int width = 500;
+ int height = 500;
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, SETTINGS, false, QSize(width, height));
+ else
+ createOffscreenAndViewer(m_viewer, SETTINGS, QSize(width, height));
+
+ Q3DSViewerSettings *s = m_viewer->settings();
+
+ QSignalSpy spy1(s, &Q3DSViewerSettings::matteColorChanged);
+ QSignalSpy spy2(s, &Q3DSViewerSettings::showRenderStatsChanged);
+ QSignalSpy spy4(s, &Q3DSViewerSettings::scaleModeChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy4.isValid());
+
+ // Check defaults
+ QCOMPARE(s->matteColor(), QColor(Qt::black));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeCenter);
+
+ // Matte
+ checkPixel(m_viewer, Qt::black);
+
+ s->setMatteColor(Qt::cyan);
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 0);
+ QCOMPARE(spy4.count(), 0);
+
+ checkPixel(m_viewer, Qt::cyan);
+
+ // Render stats
+ QImage image1 = m_viewer->grab();
+
+ s->setShowRenderStats(true);
+ QCOMPARE(s->isShowRenderStats(), true);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy4.count(), 0);
+
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+
+ s->setShowRenderStats(false);
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy4.count(), 0);
+
+ // ScaleMode
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::cyan, QPoint(50, height / 2));
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy4.count(), 1);
+
+ checkPixel(m_viewer, Qt::cyan);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+
+ checkPixel(m_viewer, Qt::blue);
+ checkPixel(m_viewer, Qt::red, QPoint(50, height / 2));
+
+ // Saving & loading settings
+ s->save(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ image1 = m_viewer->grab();
+
+ s->setMatteColor(Qt::yellow);
+ s->setShowRenderStats(true);
+ s->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(s->matteColor(), QColor(Qt::yellow));
+ QCOMPARE(s->isShowRenderStats(), true);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFit);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+
+ image2 = m_viewer->grab();
+
+ s->load(QStringLiteral("testViewer"), QStringLiteral("The Qt Company"),
+ QStringLiteral("tst_q3dsurfaceviewer"));
+
+ QCOMPARE(s->matteColor(), QColor(Qt::cyan));
+ QCOMPARE(s->isShowRenderStats(), false);
+ QCOMPARE(s->scaleMode(), Q3DSViewerSettings::ScaleModeFill);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+
+ QImage image3 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ QVERIFY(image3 != image2);
+ QVERIFY(image1 == image3);
+
+ // Clean up the settings so they don't pollute the system (and we have clean slate next time)
+ QSettings(QStringLiteral("The Qt Company"), QStringLiteral("tst_q3dsurfaceviewer")).clear();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentation_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentation()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QList<QVariant> args;
+ Q3DSPresentation *p = m_viewer->presentation();
+ QSignalSpy spy1(p, &Q3DSPresentation::slideEntered);
+ QSignalSpy spy2(p, &Q3DSPresentation::slideExited);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+
+ // There are three different "scenes":
+ // The main Scene, three slides: S1, S2, S3
+ // Two components on Scene.Layer:
+ // Scene.Layer.Component1, two slides: C1S1, C1S2
+ // Scene.Layer.Component2, two slides: C2S1, C2S2
+ // The component slides also get enter when parent slide is entered, but they do not get
+ // the corresponding exit if parent slide is exited.
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+ QPoint mainPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 2);
+ QPoint bgPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 32);
+ QPoint c1Point(m_viewer->size().width() * 5 / 8, m_viewer->size().height() / 2);
+ QPoint c2Point(m_viewer->size().width() * 7 / 8, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 0);
+
+ // String Attribute
+ QImage image1 = m_viewer->grab();
+ p->setAttribute(QStringLiteral("Scene.Layer.Text"),
+ QStringLiteral("textstring"), QStringLiteral("Test!"));
+ QImage image2 = m_viewer->grab();
+ QTRY_VERIFY(image1 != image2);
+
+ // Float Attribute
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 1.0);
+
+ checkPixel(m_viewer, Qt::cyan, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.r"), 1.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.g"), 0.0);
+ p->setAttribute(QStringLiteral("Scene.Layer.Rect.Material"),
+ QStringLiteral("diffuse.b"), 0.0);
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ // Bool Attribute
+ checkPixel(m_viewer, Qt::yellow, bgPoint);
+ p->setAttribute(QStringLiteral("Scene"), QStringLiteral("bgcolorenable"), false);
+ checkPixel(m_viewer, Qt::black, bgPoint);
+
+ // Slide changes
+ p->goToSlide(path, 2);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ // Time change
+ p->goToTime(path, 7.0f);
+ checkPixel(m_viewer, Qt::black, mainPoint);
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ // More complex slide changes
+ // Changing slide that is not visible should not trigger enter signals
+ // The slides should still change, though, and become visible later when we switch back to S1
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 1);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::cyan, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 7);
+ QCOMPARE(spy2.count(), 2);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::magenta, c2Point);
+ QCOMPARE(spy1.count(), 8);
+ QCOMPARE(spy2.count(), 3);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC1);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C1S2"));
+
+ p->goToSlide(pathC2, QStringLiteral("C2S1"));
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 4);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S1"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), pathC2);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("C2S2"));
+
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::blue, c1Point);
+ checkPixel(m_viewer, Qt::blue, c2Point);
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 5);
+
+ args = spy1.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 2);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S2"));
+ args = spy2.last();
+ QCOMPARE(args.at(0).toString(), path);
+ QCOMPARE(args.at(1).toInt(), 1);
+ QCOMPARE(args.at(2).toString(), QStringLiteral("S1"));
+
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // No wrap, should not change
+ p->goToSlide(path, false, false);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 6);
+
+ // Should wrap
+ p->goToSlide(path, false, true);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // No wrap, should not change
+ p->goToSlide(path, true, false);
+ checkPixel(m_viewer, Qt::green, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::green, c2Point);
+ QCOMPARE(spy1.count(), 14);
+ QCOMPARE(spy2.count(), 7);
+
+ // Should wrap
+ p->goToSlide(path, true, true);
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy1.count(), 17);
+ QCOMPARE(spy2.count(), 8);
+}
+
+void tst_Q3DSSurfaceViewer::testPresentationActivation_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testPresentationActivation()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, ANIMATION);
+ else
+ createOffscreenAndViewer(m_viewer, ANIMATION);
+
+ // Note: Presentation filename isn't default ID anymore, need to set manually.
+ m_viewer->setPresentationId(QStringLiteral("animation"));
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), false);
+
+ {
+ // Grab two images two seconds apart to verify animation has stopped
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 == image2);
+ }
+
+ m_viewer->presentation()->setPresentationActive(QStringLiteral("animation"), true);
+
+ {
+ // Grab two images two seconds apart to verify animation is happening
+ QImage image1 = m_viewer->grab();
+ QTest::qWait(2000);
+ QImage image2 = m_viewer->grab();
+ QVERIFY(image1 != image2);
+ }
+}
+
+void tst_Q3DSSurfaceViewer::testSceneElement_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testSceneElement()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QString path = QStringLiteral("Scene");
+ QString pathC1 = QStringLiteral("Scene.Layer.Component1");
+ QString pathC2 = QStringLiteral("Scene.Layer.Component2");
+
+ Q3DSPresentation *p = m_viewer->presentation();
+ Q3DSSceneElement *scene = new Q3DSSceneElement(path);
+ Q3DSSceneElement *sceneC1 = new Q3DSSceneElement(pathC1);
+ Q3DSSceneElement *sceneC2 = new Q3DSSceneElement(pathC2);
+ QSignalSpy spy1(scene, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy2(scene, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy3(scene, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy4(scene, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy5(scene, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy6(sceneC1, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy7(sceneC1, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy8(sceneC1, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy9(sceneC1, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy10(sceneC1, &Q3DSSceneElement::elementPathChanged);
+ QSignalSpy spy11(sceneC2, &Q3DSSceneElement::currentSlideIndexChanged);
+ QSignalSpy spy12(sceneC2, &Q3DSSceneElement::previousSlideIndexChanged);
+ QSignalSpy spy13(sceneC2, &Q3DSSceneElement::currentSlideNameChanged);
+ QSignalSpy spy14(sceneC2, &Q3DSSceneElement::previousSlideNameChanged);
+ QSignalSpy spy15(sceneC2, &Q3DSSceneElement::elementPathChanged);
+ QVERIFY(spy1.isValid());
+ QVERIFY(spy2.isValid());
+ QVERIFY(spy3.isValid());
+ QVERIFY(spy4.isValid());
+ QVERIFY(spy5.isValid());
+ QVERIFY(spy6.isValid());
+ QVERIFY(spy7.isValid());
+ QVERIFY(spy8.isValid());
+ QVERIFY(spy9.isValid());
+ QVERIFY(spy10.isValid());
+ QVERIFY(spy11.isValid());
+ QVERIFY(spy12.isValid());
+ QVERIFY(spy13.isValid());
+ QVERIFY(spy14.isValid());
+ QVERIFY(spy15.isValid());
+
+ // Defaults
+ QCOMPARE(scene->currentSlideIndex(), 0);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ checkPixel(m_viewer, Qt::red);
+
+ // Ensure we have no pending events to confuse spy counts
+ QGuiApplication::processEvents();
+
+ p->registerElement(scene);
+ p->registerElement(sceneC1);
+ p->registerElement(sceneC2);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 0);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral(""));
+ QCOMPARE(scene->elementPath(), path);
+
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 1);
+ QCOMPARE(spy2.count(), 1);
+ QCOMPARE(spy3.count(), 1);
+ QCOMPARE(spy4.count(), 1);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ QCOMPARE(spy7.count(), 0);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 0);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 0);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 0);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 0);
+ // Getting previous slide change without getting current slide change seems illogical here,
+ // but that's how the internal viewer logic for previous slide works. It makes sense when
+ // you consider the fact that we always get enter events for child slides when parent slide
+ // is entered.
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 0);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 0);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 0);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(pathC2, QStringLiteral("C2S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 2);
+ QCOMPARE(spy2.count(), 2);
+ QCOMPARE(spy3.count(), 2);
+ QCOMPARE(spy4.count(), 2);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ // Subscenes revert to original slides when parent is re-entered
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 3);
+ QCOMPARE(spy2.count(), 3);
+ QCOMPARE(spy3.count(), 3);
+ QCOMPARE(spy4.count(), 3);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 1);
+ QCOMPARE(spy7.count(), 1);
+ QCOMPARE(spy8.count(), 1);
+ QCOMPARE(spy9.count(), 1);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 1);
+ QCOMPARE(spy12.count(), 1);
+ QCOMPARE(spy13.count(), 1);
+ QCOMPARE(spy14.count(), 1);
+ QCOMPARE(spy15.count(), 0);
+
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ p->unregisterElement(scene);
+ p->unregisterElement(sceneC1);
+ p->unregisterElement(sceneC2);
+
+ // No more signals after unregistering
+ p->goToSlide(path, QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 4);
+ QCOMPARE(spy2.count(), 4);
+ QCOMPARE(spy3.count(), 4);
+ QCOMPARE(spy4.count(), 4);
+ QCOMPARE(spy5.count(), 0);
+ QCOMPARE(spy6.count(), 2);
+ QCOMPARE(spy7.count(), 2);
+ QCOMPARE(spy8.count(), 2);
+ QCOMPARE(spy9.count(), 2);
+ QCOMPARE(spy10.count(), 0);
+ QCOMPARE(spy11.count(), 2);
+ QCOMPARE(spy12.count(), 2);
+ QCOMPARE(spy13.count(), 2);
+ QCOMPARE(spy14.count(), 2);
+ QCOMPARE(spy15.count(), 0);
+
+ // Reregister
+ p->registerElement(scene);
+ p->goToSlide(path, QStringLiteral("S1"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 5);
+ QCOMPARE(spy2.count(), 5);
+ QCOMPARE(spy3.count(), 5);
+ QCOMPARE(spy4.count(), 5);
+ QCOMPARE(spy5.count(), 0);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 2);
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("S2"));
+ QCOMPARE(scene->elementPath(), path);
+
+ scene->setCurrentSlideName(QStringLiteral("S2"));
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 6);
+ QCOMPARE(spy2.count(), 6);
+
+ scene->setCurrentSlideIndex(0);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 7);
+ QCOMPARE(spy2.count(), 7);
+
+ // Go to next slide, wrap parameter doesn't matter
+ scene->goToSlide(true, true);
+ checkPixel(m_viewer, Qt::blue);
+
+ QCOMPARE(spy1.count(), 8);
+ QCOMPARE(spy2.count(), 8);
+
+ // Go to next slide, wrap parameter doesn't matter
+ scene->goToSlide(true, false);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 9);
+
+ // No wrap, should not change
+ scene->goToSlide(true, false);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 9);
+ QCOMPARE(spy2.count(), 9);
+
+ // Should wrap
+ scene->goToSlide(true, true);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 10);
+
+ // No wrap, should not change
+ scene->goToSlide(false, false);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 10);
+ QCOMPARE(spy2.count(), 10);
+
+ // Should wrap
+ scene->goToSlide(false, true);
+ checkPixel(m_viewer, Qt::green);
+
+ QCOMPARE(spy1.count(), 11);
+ QCOMPARE(spy2.count(), 11);
+
+ // Time change
+ scene->goToTime(7.0f);
+ checkPixel(m_viewer, Qt::yellow);
+
+ QCOMPARE(spy1.count(), 11);
+ QCOMPARE(spy2.count(), 11);
+
+ // Back to first slide for further tests
+ scene->setCurrentSlideIndex(0);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 12);
+ QCOMPARE(spy2.count(), 12);
+
+ // Change element path
+ scene->setElementPath(pathC1);
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 12);
+ QCOMPARE(spy2.count(), 12);
+ QCOMPARE(spy3.count(), 12);
+ QCOMPARE(spy4.count(), 12);
+ QCOMPARE(spy5.count(), 1);
+
+ QCOMPARE(scene->currentSlideIndex(), 1);
+ QCOMPARE(scene->previousSlideIndex(), 1);
+ // Having current and previous slides the same seems weird, but that's how the slide
+ // logic works internally.
+ QCOMPARE(scene->currentSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->previousSlideName(), QStringLiteral("C1S1"));
+ QCOMPARE(scene->elementPath(), pathC1);
+
+ p->goToSlide(pathC1, QStringLiteral("C1S2"));
+ checkPixel(m_viewer, Qt::red);
+
+ QCOMPARE(spy1.count(), 13);
+ QCOMPARE(spy2.count(), 12);
+ QCOMPARE(spy3.count(), 13);
+ QCOMPARE(spy4.count(), 12);
+ QCOMPARE(spy5.count(), 1);
+}
+
+void tst_Q3DSSurfaceViewer::testElement_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testElement()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MULTISLIDE);
+ else
+ createOffscreenAndViewer(m_viewer, MULTISLIDE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QString path1 = QStringLiteral("Scene.Layer.Rect.Material"); // Red
+ QString path2 = QStringLiteral("Scene.Layer.Component1.Rectangle4.Material"); // Green
+ QString path3 = QStringLiteral("Scene.Layer.Component2.Rectangle6.Material"); // Yellow
+
+ QPoint mainPoint(m_viewer->size().width() * 2 / 8, m_viewer->size().height() / 2);
+ QPoint c1Point(m_viewer->size().width() * 5 / 8, m_viewer->size().height() / 2);
+ QPoint c2Point(m_viewer->size().width() * 7 / 8, m_viewer->size().height() / 2);
+
+ Q3DSPresentation *p = m_viewer->presentation();
+ Q3DSElement *element1 = new Q3DSElement(p, path1);
+ Q3DSElement *element2 = new Q3DSElement(p, path2);
+ QSignalSpy spy2(element2, &Q3DSSceneElement::elementPathChanged);
+ QVERIFY(spy2.isValid());
+
+ checkPixel(m_viewer, Qt::red, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ element1->setAttribute(QStringLiteral("diffuse.r"), 0.0);
+ element1->setAttribute(QStringLiteral("diffuse.g"), 0.0);
+ element1->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::green, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ element2->setAttribute(QStringLiteral("diffuse.r"), 1.0);
+ element2->setAttribute(QStringLiteral("diffuse.g"), 0.0);
+ element2->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+
+ // Change elementpath, nothing changes visually
+ element2->setElementPath(path3);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::yellow, c2Point);
+ QCOMPARE(spy2.count(), 1);
+
+ element2->setAttribute(QStringLiteral("diffuse.r"), 0.0);
+ element2->setAttribute(QStringLiteral("diffuse.g"), 1.0);
+ element2->setAttribute(QStringLiteral("diffuse.b"), 1.0);
+ checkPixel(m_viewer, Qt::blue, mainPoint);
+ checkPixel(m_viewer, Qt::magenta, c1Point);
+ checkPixel(m_viewer, Qt::cyan, c2Point);
+}
+
+void tst_Q3DSSurfaceViewer::testMouseInput_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testMouseInput()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, MOUSE);
+ else
+ createOffscreenAndViewer(m_viewer, MOUSE);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QPoint point1(m_viewer->size().width() * 1 / 4, m_viewer->size().height() / 2);
+ QPoint point2(m_viewer->size().width() * 3 / 4, m_viewer->size().height() / 2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e1(QEvent::MouseButtonPress, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e1);
+
+ checkPixel(m_viewer, Qt::green, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e2(QEvent::MouseButtonRelease, point1, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e2);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ QMouseEvent e3(QEvent::MouseButtonPress, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mousePressEvent(&e3);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::blue, point2);
+
+ QMouseEvent e4(QEvent::MouseButtonRelease, point2, Qt::LeftButton, Qt::LeftButton,
+ Qt::NoModifier);
+ m_viewer->presentation()->mouseReleaseEvent(&e4);
+
+ checkPixel(m_viewer, Qt::blue, point1);
+ checkPixel(m_viewer, Qt::red, point2);
+
+ // Note: No way yet to hook mouse move into anything in the presentation
+}
+
+void tst_Q3DSSurfaceViewer::testDataInput_data()
+{
+ testBasics_data();
+}
+
+void tst_Q3DSSurfaceViewer::testDataInput()
+{
+ QFETCH(bool, isWindow);
+
+ if (isWindow)
+ createWindowAndViewer(m_viewer, DATAINPUT);
+ else
+ createOffscreenAndViewer(m_viewer, DATAINPUT);
+
+ m_viewer->settings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QPoint point1(m_viewer->size().width() / 4, m_viewer->size().height() / 4);
+
+ const QString animationName = QStringLiteral("animationInput");
+ const QString slideName = QStringLiteral("slideInput");
+
+ checkPixel(m_viewer, Qt::red, point1);
+ m_viewer->presentation()->setDataInputValue(animationName, 90);
+ checkPixel(m_viewer, Qt::blue, point1);
+ m_viewer->presentation()->setDataInputValue(animationName, 10);
+ checkPixel(m_viewer, Qt::red, point1);
+
+ Q3DSDataInput *animationInput = new Q3DSDataInput();
+ animationInput->setName(animationName);
+
+ m_viewer->presentation()->registerDataInput(animationInput);
+ QVERIFY(m_viewer->presentation()->registeredDataInput(animationInput->name()));
+
+ Q3DSDataInput *slideInput = new Q3DSDataInput(m_viewer->presentation(), slideName);
+ QVERIFY(m_viewer->presentation()->registeredDataInput(slideInput->name()));
+
+ animationInput->setValue(90);
+ checkPixel(m_viewer, Qt::blue, point1);
+ animationInput->setValue(10);
+ checkPixel(m_viewer, Qt::red, point1);
+
+ slideInput->setValue(QStringLiteral("Slide2"));
+ checkPixel(m_viewer, Qt::green, point1);
+ slideInput->setValue(QStringLiteral("Slide1"));
+ checkPixel(m_viewer, Qt::red, point1);
+
+ m_viewer->presentation()->unregisterDataInput(animationInput);
+ m_viewer->presentation()->unregisterDataInput(slideInput);
+ QVERIFY(!m_viewer->presentation()->registeredDataInput(animationInput->name()));
+ QVERIFY(!m_viewer->presentation()->registeredDataInput(slideInput->name()));
+ delete animationInput;
+ delete slideInput;
+}
+
+
+QTEST_MAIN(tst_Q3DSSurfaceViewer)
+
+#include "tst_q3dssurfaceviewer.moc"
diff --git a/tests/auto/studio3d/shared/presentation/animation.uip b/tests/auto/studio3d/shared/presentation/animation.uip
new file mode 100644
index 0000000..bd78b51
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/animation.uip
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Cube" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="29690" />
+ <Set ref="#Camera" endtime="29690" />
+ <Set ref="#Light" endtime="29690" />
+ <Add ref="#Cube" name="Cube" endtime="29690" position="5.7735 -14.4338 0" sourcepath="#Cube" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -457.55 100 100 4.832 -8.66028 100 100 11.174 440.23 100 100 20.037 -64.9519 100 100 29.69 -401.258 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 -1.52588e-05 100 100 4.832 -220.837 100 100 11.174 -18.7639 100 100 20.037 225.167 100 100 29.69 -14.4337 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 4.832 0 100 100 11.174 0 100 100 20.037 0 100 100 29.69 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/blue.uip b/tests/auto/studio3d/shared/presentation/blue.uip
new file mode 100644
index 0000000..a6eefa7
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/blue.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/datainput.uia b/tests/auto/studio3d/shared/presentation/datainput.uia
new file mode 100644
index 0000000..fbfa55b
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/datainput.uia
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<application>
+ <assets initial="datainput">
+ <dataInput name="animationInput" type="Ranged Number" min="0" max="100"/>
+ <dataInput name="slideInput" type="String" />
+ <presentation id="datainput" src="datainput.uip"/>
+ <presentation id="subpres" src="datainput_sub.uip"/>
+ </assets>
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Initial">
+ <enter>
+ <goto-slide element="main:Scene" rel="next"/>
+ </enter>
+ </state>
+ </visual-states>
+ </statemachine>
+</application>
diff --git a/tests/auto/studio3d/shared/presentation/datainput.uip b/tests/auto/studio3d/shared/presentation/datainput.uip
new file mode 100644
index 0000000..3807cec
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/datainput.uip
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="600" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Graph >
+ <Scene id="Scene" backgroundcolor="0 1 0" controlledproperty="$animationInput @timeline $slideInput @slide" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Component id="Component" >
+ <Text id="Text" />
+ </Component>
+ <Model id="Rectangle" >
+ <Material id="Default" name="Default" >
+ <Image id="Default_diffusemap" />
+ </Material>
+ </Model>
+ <Text id="Text_001" />
+ <Model id="Rectangle2" >
+ <Material id="Default_001" name="Default" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" background="Transparent" sourcepath="" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" />
+ <Add ref="#Rectangle" name="Rectangle" sourcepath="#Rectangle" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -327.165 100 100 10 351.542 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 -6.41502 100 100 10 -17.962 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Default" diffusemap="#Default_diffusemap" />
+ <Add ref="#Default_diffusemap" sourcepath="maps/QT-symbol.png" subpresentation="subpres" />
+ <State id="Scene-Slide1" name="Slide1" initialplaystate="Pause" >
+ <Add ref="#Component" name="Component" controlledproperty="$animationInput @timeline" />
+ <Add ref="#Rectangle2" name="Rectangle2" position="0 0 100" scale="9999 9999 99999" sourcepath="#Rectangle" />
+ <Add ref="#Default_001" >
+ <AnimationTrack property="diffuse.x" type="EaseInOut" >0 1 100 100 4.487 1 100 100 5.5 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.y" type="EaseInOut" >0 0 100 100 4.487 0 100 100 5.5 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="diffuse.z" type="EaseInOut" >0 0 100 100 4.487 0 100 100 5.5 1 100 100 10 1 100 100</AnimationTrack>
+ </Add>
+ </State>
+ <State id="Scene-Slide2" name="Slide2" initialplaystate="Play" playmode="Stop at end" playthroughto="Previous" >
+ <Add ref="#Text_001" name="Text" font="TitilliumWeb-Regular" position="-442.635 -193.733 0" textstring="Second slide" />
+ </State>
+ </State>
+ <State name="Master Slide" component="#Component" >
+ <State id="Component-Slide1" name="Slide1" initialplaystate="Pause" >
+ <Add ref="#Text" name="Text" controlledproperty="$animationInput textstring" font="TitilliumWeb-Regular" position="-5.132 137.281 0" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 10 -360 100 100</AnimationTrack>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/datainput_sub.uip b/tests/auto/studio3d/shared/presentation/datainput_sub.uip
new file mode 100644
index 0000000..c007eab
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/datainput_sub.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="400" presentationHeight="200" maintainAspect="False" >
+ <CustomColors count="16" >#ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Graph >
+ <Scene id="Scene" controlledproperty="$animationInput @timeline" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Text id="Text" controlledproperty="$slideInput textstring" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" />
+ <State id="Scene-Slide1" name="Slide1" initialplaystate="Pause" >
+ <Add ref="#Text" name="Text" font="TitilliumWeb-Regular" opacity="99" size="96" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 10 -360 100 100</AnimationTrack>
+ </Add>
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf b/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf
new file mode 100644
index 0000000..6da8219
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/fonts/TitilliumWeb-Regular.ttf
Binary files differ
diff --git a/tests/auto/studio3d/shared/presentation/mixed.uip b/tests/auto/studio3d/shared/presentation/mixed.uip
new file mode 100644
index 0000000..16fea00
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mixed.uip
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="401.651 25 0" scale="8 16 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="-378.164 25 0" scale="8 16 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/mixed_vertical.uip b/tests/auto/studio3d/shared/presentation/mixed_vertical.uip
new file mode 100644
index 0000000..7914b11
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mixed_vertical.uip
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -400 0" scale="16 8 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="0 400 0" scale="16 8 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/mouse.uip b/tests/auto/studio3d/shared/presentation/mouse.uip
new file mode 100644
index 0000000..edd9f95
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/mouse.uip
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="668.283 7.21691 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <Action id="Rectangle-Action" eyeball="True" triggerObject="#Rectangle" event="onPressureDown" targetObject="#Material" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 0 1" />
+ </Action>
+ <Action id="Rectangle-Action_001" eyeball="True" triggerObject="#Rectangle" event="onPressureUp" targetObject="#Material" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="1 0 0" />
+ </Action>
+ </Add>
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ <Add ref="#Rectangle2" name="Rectangle2" endtime="8000" position="-528.276 -19.6247 0" scale="10.6053 8.67004 1" sourcepath="#Rectangle" >
+ <Action id="Rectangle2-Action" eyeball="True" triggerObject="#Rectangle2" event="onPressureDown" targetObject="#Material_001" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 1 0" />
+ </Action>
+ <Action id="Rectangle2-Action_001" eyeball="True" triggerObject="#Rectangle2" event="onPressureUp" targetObject="#Material_001" handler="Set Property" >
+ <HandlerArgument name="Property Name" type="String" argtype="Property" value="diffuse" />
+ <HandlerArgument name="Property Value" type="Float3" argtype="Dependent" value="0 0 1" />
+ </Action>
+ </Add>
+ <Add ref="#Material_001" diffuse="0 0 1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/multislide.uip b/tests/auto/studio3d/shared/presentation/multislide.uip
new file mode 100644
index 0000000..e17db1d
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/multislide.uip
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" backgroundcolor="1 1 0" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle1" >
+ <Material id="Material" />
+ </Model>
+ <Model id="Rectangle2" >
+ <Material id="Material_001" />
+ </Model>
+ <Model id="Rectangle2_003" >
+ <Material id="Material_006" />
+ </Model>
+ <Component id="Component" >
+ <Model id="Rectangle" >
+ <Material id="Material_002" />
+ </Model>
+ <Model id="Rectangle2_001" >
+ <Material id="Material_003" />
+ </Model>
+ </Component>
+ <Component id="Component2" >
+ <Model id="Rectangle_001" >
+ <Material id="Material_004" />
+ </Model>
+ <Model id="Rectangle2_002" >
+ <Material id="Material_005" />
+ </Model>
+ </Component>
+ <Text id="Text" />
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-S1" name="S1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle1" name="Rect" position="0 0 0" scale="13.3333 5 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" opacity="100" />
+ <Add ref="#Component" name="Component1" endtime="8000" position="400 0 -1" scale="4 3 1" />
+ <Add ref="#Component2" name="Component2" endtime="8000" position="461.548 -5.72538 -5" />
+ <Add ref="#Text" name="Text" endtime="8000" font="TitilliumWeb-Regular" position="-304.552 -193.631 0" size="36" />
+ </State>
+ <State id="Scene-S2" name="S2" initialplaystate="Pause" playmode="Looping" playthroughto="Previous" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle2" name="Rectangle2" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 11.6 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 9.5252 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 8 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_001" diffuse="0 0 1" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ <State id="Scene-S3" name="S3" initialplaystate="Pause" playmode="Looping" playthroughto="Previous" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle2_003" name="Rectangle3" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" >
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 11.6 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 9.5252 100 100 8 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 8 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Material_006" diffuse="0 1 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ <State name="Master Slide" component="#Component" >
+ <State id="Component1-C1S1" name="C1S1" >
+ <Add ref="#Rectangle" name="Rectangle4" position="0 0 -1" scale="2 3 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_002" diffuse="0 1 0" />
+ </State>
+ <State id="Component1-C1S2" name="C1S2" playthroughto="Previous" >
+ <Add ref="#Rectangle2_001" name="Rectangle5" position="0 0 -1" scale="2 3 1" sourcepath="#Rectangle" />
+ <Add ref="#Material_003" diffuse="0 1 1" />
+ </State>
+ </State>
+ <State name="Master Slide" component="#Component2" >
+ <State id="Component2-C2S1" name="C2S1" >
+ <Add ref="#Rectangle_001" name="Rectangle6" scale="3.5 7 3.03591" sourcepath="#Rectangle" />
+ <Add ref="#Material_004" diffuse="1 1 0" />
+ </State>
+ <State id="Component2-C2S2" name="C2S2" playthroughto="Previous" >
+ <Add ref="#Rectangle2_002" name="Rectangle7" scale="3.5 7 3.03591" sourcepath="#Rectangle" />
+ <Add ref="#Material_005" diffuse="1 0 1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/red.uip b/tests/auto/studio3d/shared/presentation/red.uip
new file mode 100644
index 0000000..a04d2f8
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/red.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="800" presentationHeight="480" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" endtime="8000" position="0 -15.8771 0" scale="13.3333 9.5252 1" sourcepath="#Rectangle" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/presentation/settings.uip b/tests/auto/studio3d/shared/presentation/settings.uip
new file mode 100644
index 0000000..acd580a
--- /dev/null
+++ b/tests/auto/studio3d/shared/presentation/settings.uip
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="3" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="300" presentationHeight="200" maintainAspect="False" />
+ <Graph >
+ <Scene id="Scene" backgroundcolor="0 0 1" >
+ <Layer id="Layer" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Rectangle" >
+ <Material id="Material" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" lighttype="Directional" position="0 0 -500" rotation="0 0 0" />
+ <State id="Scene-Slide1" name="Slide1" playmode="Looping" >
+ <Set ref="#Layer" endtime="8000" />
+ <Set ref="#Camera" endtime="8000" />
+ <Set ref="#Light" endtime="8000" />
+ <Add ref="#Rectangle" name="Rectangle" edgetess="1" endtime="8000" innertess="1" position="0 -15.8771 0" scale="11 2.375 1" sourcepath="#Rectangle" tessellation="Linear" />
+ <Add ref="#Material" diffuse="1 0 0" emissivecolor="1 1 1" emissivepower="1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/auto/studio3d/shared/shared_presentations.h b/tests/auto/studio3d/shared/shared_presentations.h
new file mode 100644
index 0000000..6d38273
--- /dev/null
+++ b/tests/auto/studio3d/shared/shared_presentations.h
@@ -0,0 +1,39 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qurl.h>
+
+const QUrl RED = QUrl(QStringLiteral("qrc:/red.uip"));
+const QUrl BLUE = QUrl(QStringLiteral("qrc:/blue.uip"));
+const QUrl MIXED = QUrl(QStringLiteral("qrc:/mixed.uip"));
+const QUrl MIXED_VERTICAL = QUrl(QStringLiteral("qrc:/mixed_vertical.uip"));
+const QUrl ANIMATION = QUrl(QStringLiteral("qrc:/animation.uip"));
+const QUrl SETTINGS = QUrl(QStringLiteral("qrc:/settings.uip"));
+const QUrl MULTISLIDE = QUrl(QStringLiteral("qrc:/multislide.uip"));
+const QUrl MOUSE = QUrl(QStringLiteral("qrc:/mouse.uip"));
+const QUrl DATAINPUT = QUrl(QStringLiteral("qrc:/datainput.uia"));
diff --git a/tests/auto/studio3d/shared/shared_presentations.qrc b/tests/auto/studio3d/shared/shared_presentations.qrc
new file mode 100644
index 0000000..d4bb668
--- /dev/null
+++ b/tests/auto/studio3d/shared/shared_presentations.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="blue.uip">presentation/blue.uip</file>
+ <file alias="red.uip">presentation/red.uip</file>
+ <file alias="mixed.uip">presentation/mixed.uip</file>
+ <file alias="animation.uip">presentation/animation.uip</file>
+ <file alias="mixed_vertical.uip">presentation/mixed_vertical.uip</file>
+ <file alias="settings.uip">presentation/settings.uip</file>
+ <file alias="multislide.uip">presentation/multislide.uip</file>
+ <file alias="mouse.uip">presentation/mouse.uip</file>
+ <file alias="datainput.uip">presentation/datainput.uip</file>
+ <file alias="datainput.uia">presentation/datainput.uia</file>
+ <file alias="datainput_sub.uip">presentation/datainput_sub.uip</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/studio3d/studio3d.pro b/tests/auto/studio3d/studio3d.pro
new file mode 100644
index 0000000..e92019f
--- /dev/null
+++ b/tests/auto/studio3d/studio3d.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ q3dssurfaceviewer
diff --git a/tests/auto/viewer/tst_qt3dsviewer.cpp b/tests/auto/viewer/tst_qt3dsviewer.cpp
new file mode 100644
index 0000000..c9787fd
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.cpp
@@ -0,0 +1,762 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "tst_qt3dsviewer.h"
+
+#include <QtQuick/QQuickItem>
+#include <QtGui/QSurfaceFormat>
+#include <QtStudio3D/Q3DSPresentation>
+#include <QtStudio3D/Q3DSElement>
+#include <QtStudio3D/Q3DSViewerSettings>
+#include <QtStudio3D/Q3DSGeometry>
+#include <QtCore/QRandomGenerator>
+#include <QtCore/QFile>
+#include <QtCore/QTextStream>
+#include <QtCore/QRegularExpression>
+
+void messageOutput(QtMsgType type, const QMessageLogContext &context,
+ const QString &msg)
+{
+ Q_UNUSED(context);
+ switch (type) {
+ case QtDebugMsg:
+ case QtInfoMsg:
+ case QtWarningMsg:
+ case QtCriticalMsg:
+ break; // swallow
+ case QtFatalMsg:
+ QFAIL(msg.toLocal8Bit().constData());
+ }
+}
+
+void tst_qt3dsviewer::initTestCase()
+{
+ qInstallMessageHandler(messageOutput);
+}
+
+void tst_qt3dsviewer::cleanupTestCase()
+{
+}
+
+void tst_qt3dsviewer::init()
+{
+#if defined(Q_OS_ANDROID)
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(3, 2);
+ format.setProfile(QSurfaceFormat::CompatibilityProfile);
+ format.setRenderableType(QSurfaceFormat::OpenGLES);
+#else
+ QSurfaceFormat format;
+ format.setDepthBufferSize(32);
+ format.setVersion(4, 3);
+ format.setProfile(QSurfaceFormat::CoreProfile);
+ QSurfaceFormat::setDefaultFormat(format);
+#endif
+
+ m_viewer = new QQuickView;
+ m_viewer->setTitle(QStringLiteral("tst_qt3dsviewer"));
+ m_viewer->setSource(QUrl("qrc:/tst_qt3dsviewer.qml"));
+ m_studio3DItem = m_viewer->rootObject();
+ m_presentation = nullptr;
+ m_settings = nullptr;
+ m_ignoreError = false;
+
+ QVERIFY(m_studio3DItem);
+
+ const auto children = m_studio3DItem->children();
+ for (auto &child : children) {
+ if (!m_presentation)
+ m_presentation = qobject_cast<Q3DSPresentation *>(child);
+ if (!m_settings)
+ m_settings = qobject_cast<Q3DSViewerSettings *>(child);
+ }
+
+ QVERIFY(m_presentation);
+ QVERIFY(m_settings);
+}
+
+void tst_qt3dsviewer::cleanup()
+{
+ deleteCreated();
+ if (!m_ignoreError)
+ QCOMPARE(m_studio3DItem->property("error").toString(), {});
+ m_studio3DItem = nullptr;
+ m_viewer->hide();
+ m_viewer->deleteLater();
+ m_viewer = nullptr;
+}
+
+void tst_qt3dsviewer::testEmpty()
+{
+ m_presentation->setProperty("source", QUrl());
+ m_viewer->show();
+ QTest::qWait(1000);
+ QCOMPARE(m_studio3DItem->property("running").toBool(), false);
+ QVERIFY(!m_studio3DItem->property("error").toString().isEmpty());
+ m_ignoreError = true; // To avoid triggering cleanup() fail as we are expecting an error
+}
+
+void tst_qt3dsviewer::testLoading()
+{
+ QCOMPARE(m_studio3DItem->property("running").toBool(), false);
+ m_viewer->show();
+ QTest::qWait(1000);
+ QCOMPARE(m_studio3DItem->property("running").toBool(), true);
+}
+
+
+void tst_qt3dsviewer::testSlides()
+{
+ QSignalSpy spyEntered(m_presentation,
+ SIGNAL(slideEntered(const QString &, unsigned int, const QString &)));
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ QCOMPARE(spyEntered.count(), 0);
+ QCOMPARE(spyExited.count(), 0);
+
+ m_viewer->show();
+ QTest::qWait(1000);
+
+ QCOMPARE(spyEntered.count(), 1);
+ QCOMPARE(spyExited.count(), 0);
+
+ QVERIFY(spyExited.wait(12000));
+ QCOMPARE(spyEntered.count(), 2);
+ QCOMPARE(spyExited.count(), 1);
+}
+
+void tst_qt3dsviewer::testFrameUpdates()
+{
+ QSignalSpy spyFrames(m_studio3DItem, SIGNAL(frameUpdate()));
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ m_viewer->show();
+ QVERIFY(spyExited.wait(12000));
+ // Just ensure we get some frames, exact count will vary a lot due to external factors
+ QVERIFY(spyFrames.count() > 10);
+}
+
+void tst_qt3dsviewer::testSettings()
+{
+ m_viewer->show();
+ m_settings->setMatteColor(QColor("#0000ff"));
+ QVERIFY(m_settings->matteColor() == QColor("#0000ff"));
+
+ // Save and change matte color
+ m_settings->save("", "tst_qt3dsviewer", "tst_qt3dsviewer");
+ m_settings->setMatteColor(QColor("#00ff00"));
+ QVERIFY(m_settings->matteColor() == QColor("#00ff00"));
+ // Load and previous matte color should be back
+ m_settings->load("", "tst_qt3dsviewer", "tst_qt3dsviewer");
+ QVERIFY(m_settings->matteColor() == QColor("#0000ff"));
+}
+
+void tst_qt3dsviewer::testCreateElement()
+{
+ m_viewer->show();
+
+ m_settings->setShowRenderStats(true);
+ m_settings->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementsCreated(const QStringList &,
+ const QString &)));
+
+ QObject::connect(m_presentation, &Q3DSPresentation::elementsCreated,
+ [this](const QStringList &elementNames, const QString &error) {
+ QCOMPARE(error, QString());
+ for (const auto &elementName : elementNames)
+ QVERIFY(m_createdElements.contains(elementName));
+ });
+
+ auto loadMatDefFile = [&](const QString &fileName) -> QString {
+ QFile matDefFile(fileName);
+ if (!matDefFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ return {};
+
+ QTextStream in(&matDefFile);
+ return in.readAll();
+ };
+
+ int animValue = 0;
+
+ QString md = loadMatDefFile(QStringLiteral(
+ ":/scenes/simple_cube_animation/materials/Basic Red.materialdef"));
+ m_presentation->createMaterial(md);
+ m_createdMaterials << QStringLiteral("materials/Basic Red");
+ md = loadMatDefFile(QStringLiteral(
+ ":/scenes/simple_cube_animation/materials/Basic Green.materialdef"));
+ m_presentation->createMaterial(md);
+ m_createdMaterials << QStringLiteral("materials/Basic Green");
+
+
+ QHash<QString, QVariant> data;
+ data.insert(QStringLiteral("name"), QStringLiteral("New Cylinder"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QString());
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 4500);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(200, 300, 200)));
+ data.insert(QStringLiteral("opacity"), 20.0);
+ data.insert(QStringLiteral("controlledproperty"), QStringLiteral("@newDataInput opacity"));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+
+ // Elements can be registered before they are created
+ Q3DSElement newCylinder(m_presentation, QStringLiteral("Scene.Layer.New Cylinder"));
+ Q3DSElement newCylinder2(m_presentation,
+ QStringLiteral("Scene.Layer.New Cylinder.New Cylinder 2"));
+ Q3DSElement newGroup(m_presentation, QStringLiteral("Scene.Layer.New Group"));
+ Q3DSElement newSphere(m_presentation, QStringLiteral("Scene.Layer.Cube2.New Sphere"));
+
+ QTimer animationTimer;
+ animationTimer.setInterval(10);
+ int animDir = 1;
+ QObject::connect(&animationTimer, &QTimer::timeout, [&]() {
+ if (qAbs(animValue) > 100)
+ animDir = -animDir;
+ animValue += animDir;
+ newCylinder.setAttribute(QStringLiteral("rotation.x"), animValue * 4);
+ newCylinder2.setAttribute(QStringLiteral("position.y"), animValue * 3);
+ newSphere.setAttribute(QStringLiteral("position.x"), 50 + animValue * 2);
+ newGroup.setAttribute(QStringLiteral("opacity"), qAbs(animValue));
+ m_presentation->setDataInputValue(QStringLiteral("newDataInput"), qAbs(animValue / 2));
+ });
+
+ // Create objects to slides 1 & 2 while slide 1 is executing
+ QTimer::singleShot(1000, [&]() {
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Cylinder 2"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Red"));
+ data.insert(QStringLiteral("starttime"), 500);
+ data.insert(QStringLiteral("endtime"), 5000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(50, animValue, 50)));
+
+ createElement(QStringLiteral("Scene.Layer.New Cylinder"),
+ QStringLiteral("Slide1"), data);
+
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Sphere"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 1000);
+ data.insert(QStringLiteral("endtime"), 4000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(animValue, 75, 0)));
+
+ createElement(QStringLiteral("Scene.Layer.Cube2"), QStringLiteral("Slide2"), data);
+
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("Sphere To Delete"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Red"));
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 10000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-100, -100, 0)));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"), data);
+
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("group"));
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 10000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(50, -100, 0)));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+
+ QVector<QHash<QString, QVariant>> groupElemProps;
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("Child 1 of Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("model"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 1000);
+ data.insert(QStringLiteral("endtime"), 4000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(0, 0, 0)));
+ groupElemProps << data;
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("Child 2 of Group"));
+ data.insert(QStringLiteral("type"), QStringLiteral("model"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 2000);
+ data.insert(QStringLiteral("endtime"), 4000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(100, 0, 0)));
+ groupElemProps << data;
+
+ m_createdElements << QStringLiteral("Scene.Layer.New Group.Child 1 of Group")
+ << QStringLiteral("Scene.Layer.New Group.Child 2 of Group");
+
+ m_presentation->createElements(QStringLiteral("Scene.Layer.New Group"),
+ QStringLiteral("Slide1"), groupElemProps);
+
+ animationTimer.start();
+ });
+
+ // Switch to slide 2
+ QVERIFY(spyExited.wait(20000));
+
+ // Remove dynamically added object
+ QTimer::singleShot(3000, [&]() {
+ m_presentation->deleteElement(QStringLiteral("Scene.Layer.Sphere To Delete"));
+ m_createdElements.removeOne(QStringLiteral("Scene.Layer.Sphere To Delete"));
+ });
+
+ // Create objects to slides 1 and 2 while slide 2 is executing
+ QTimer::singleShot(2000, [&]() {
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Cylinder 3"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 3000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-100, -100, 0)));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+
+ data.clear();
+ data.insert(QStringLiteral("name"), QStringLiteral("New Sphere 2"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Green"));
+ data.insert(QStringLiteral("starttime"), 0);
+ data.insert(QStringLiteral("endtime"), 5000);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-100, 100, 0)));
+
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"), data);
+ });
+
+ // Switch to slide 1
+ QVERIFY(spyExited.wait(20000));
+
+ QRandomGenerator rnd;
+ QVector<QHash<QString, QVariant>> massProps;
+ for (int i = 0; i < 1000; ++i) {
+ data.clear();
+ QString elementName = QStringLiteral("MassElement_%1").arg(i);
+ data.insert(QStringLiteral("name"), elementName);
+ data.insert(QStringLiteral("sourcepath"),
+ i % 2 ? QStringLiteral("#Cube") : QStringLiteral("#Cone"));
+ data.insert(QStringLiteral("material"),
+ i % 2 ? QStringLiteral("Basic Green") : QStringLiteral("Basic Red"));
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(rnd.bounded(-600, 600),
+ rnd.bounded(-600, 600),
+ rnd.bounded(800, 1200))));
+ massProps << data;
+ m_createdElements << QStringLiteral("Scene.Layer.") + elementName;
+ }
+ m_presentation->createElements(QStringLiteral("Scene.Layer"), QStringLiteral("Slide2"),
+ massProps);
+
+ // Switch to slide 2
+ QVERIFY(spyExited.wait(20000));
+
+ QTest::qWait(500);
+ QCOMPARE(spyElemCreated.count(), 9);
+ const QStringList createdElements = m_presentation->createdElements();
+ QCOMPARE(createdElements.size(), m_createdElements.size());
+ for (const auto &elementName : createdElements)
+ QVERIFY(m_createdElements.contains(elementName));
+ deleteCreated();
+
+ // Switch to slide 1
+ QVERIFY(spyExited.wait(20000));
+ QTest::qWait(1000);
+}
+
+void tst_qt3dsviewer::testCreateMaterial()
+{
+ m_viewer->show();
+
+ m_settings->setShowRenderStats(true);
+ m_settings->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ QSignalSpy spyMatCreated(m_presentation, SIGNAL(materialsCreated(const QStringList &,
+ const QString &)));
+ QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementsCreated(const QStringList &,
+ const QString &)));
+
+ QStringList materialDefinitions;
+ // Create material via .materialdef file in resources
+ materialDefinitions
+ << QStringLiteral(":/scenes/simple_cube_animation/materials/Basic Blue.materialdef")
+ << QStringLiteral(":/scenes/simple_cube_animation/materials/Basic Texture.materialdef");
+
+ // Create material directly from materialdef content
+ auto loadMatDefFile = [&](const QString &fileName) -> QString {
+ QFile matDefFile(fileName);
+ if (!matDefFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ return {};
+
+ QTextStream in(&matDefFile);
+ return in.readAll();
+ };
+ QString matDef = loadMatDefFile(
+ QStringLiteral(":/scenes/simple_cube_animation/materials/Copper.materialdef"));
+ QVERIFY(!matDef.isEmpty());
+ materialDefinitions << matDef;
+
+ m_presentation->createMaterials(materialDefinitions);
+ m_createdMaterials << QStringLiteral("materials/Basic Blue")
+ << QStringLiteral("materials/Basic Texture")
+ << QStringLiteral("materials/Copper");
+
+ QObject::connect(m_presentation, &Q3DSPresentation::materialsCreated,
+ [this](const QStringList &materialNames, const QString &error) {
+ QCOMPARE(error, QString());
+ for (auto &name : materialNames) {
+ QVERIFY(m_createdMaterials.contains(name));
+ QHash<QString, QVariant> data;
+ if (name == QLatin1String("materials/Basic Blue")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Blue Cylinder"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cylinder"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(200, 300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Basic Texture")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Textured Cone"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cone"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-200, -300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Copper")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Copper Sphere"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Sphere"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-200, 300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else if (name == QLatin1String("materials/Just Yellow")) {
+ QHash<QString, QVariant> data;
+ data.insert(QStringLiteral("name"), QStringLiteral("Yellow Cube"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cube"));
+ data.insert(QStringLiteral("material"), name);
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(200, -300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else {
+ QVERIFY(false);
+ }
+ }
+ });
+
+ // Create material after start
+ QTimer::singleShot(1000, [&]() {
+ QString md = loadMatDefFile(QStringLiteral(
+ ":/scenes/simple_cube_animation/materials/Basic Blue.materialdef"));
+ // Modify the diffuse color and material name so that we can be sure it is a new one
+ md.replace(QStringLiteral("Basic Blue"), QStringLiteral("Just Yellow"));
+ md.replace(QRegularExpression(QStringLiteral("\"diffuse\">.*<")),
+ QStringLiteral("\"diffuse\">1 1 0 1<"));
+ m_presentation->createMaterial(md);
+ m_createdMaterials << QStringLiteral("materials/Just Yellow");
+ });
+
+ // Delete material
+ QTimer::singleShot(2500, [&]() {
+ m_presentation->deleteElement(QStringLiteral("Scene.Layer.Textured Cone"));
+ m_presentation->deleteMaterial("materials/Basic Texture");
+ m_createdMaterials.removeOne(QStringLiteral("materials/Basic Texture"));
+
+ // Try to use the deleted material - should find a fallback material
+ QHash<QString, QVariant> data;
+ data.insert(QStringLiteral("name"), QStringLiteral("Textured Cone 2"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("#Cone"));
+ data.insert(QStringLiteral("material"), QStringLiteral("materials/Basic Texture"));
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(-100, -300, 200)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ });
+
+ QVERIFY(spyExited.wait(20000));
+ QCOMPARE(spyMatCreated.count(), 2);
+ QCOMPARE(spyElemCreated.count(), 5);
+ const QStringList createdMaterials = m_presentation->createdMaterials();
+ QCOMPARE(createdMaterials.size(), m_createdMaterials.size());
+ for (const auto &name : createdMaterials)
+ QVERIFY(m_createdMaterials.contains(name));
+ deleteCreated();
+ QTest::qWait(200); // Extra wait to verify slide change visually
+}
+
+void tst_qt3dsviewer::testCreateMesh()
+{
+ m_viewer->show();
+
+ m_settings->setShowRenderStats(true);
+ m_settings->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
+
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+ QSignalSpy spyMeshCreated(m_presentation, SIGNAL(meshesCreated(const QStringList &,
+ const QString &)));
+ QSignalSpy spyElemCreated(m_presentation, SIGNAL(elementsCreated(const QStringList &,
+ const QString &)));
+ Q3DSGeometry pyramid;
+ Q3DSGeometry star;
+ createGeometries(pyramid, star);
+
+ Q3DSElement pyramidElem(m_presentation, QStringLiteral("Scene.Layer.Pyramid"));
+ Q3DSElement starElem(m_presentation, QStringLiteral("Scene.Layer.Star"));
+
+ int animValue = 0;
+ QTimer animationTimer;
+ animationTimer.setInterval(10);
+ QObject::connect(&animationTimer, &QTimer::timeout, [&]() {
+ animValue++;
+ pyramidElem.setAttribute(QStringLiteral("rotation.x"), animValue * 2);
+ pyramidElem.setAttribute(QStringLiteral("rotation.y"), animValue);
+ starElem.setAttribute(QStringLiteral("rotation.x"), -animValue * 2);
+ starElem.setAttribute(QStringLiteral("rotation.y"), -animValue);
+ });
+
+ m_presentation->createMaterial(
+ QStringLiteral(":/scenes/simple_cube_animation/materials/Basic Texture.materialdef"));
+ m_createdMaterials << QStringLiteral("materials/Basic Texture");
+ m_presentation->createMesh(QStringLiteral("Pyramid"), pyramid);
+ m_createdMeshes << QStringLiteral("Pyramid");
+
+ QObject::connect(m_presentation, &Q3DSPresentation::meshesCreated,
+ [&](const QStringList &meshNames, const QString &error) {
+ QCOMPARE(error, QString());
+ for (auto &name : meshNames) {
+ QVERIFY(m_createdMeshes.contains(name));
+ QHash<QString, QVariant> data;
+ if (name == QLatin1String("Pyramid")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Pyramid"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("Pyramid"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Texture"));
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(100, 150, 500)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ animationTimer.start();
+ } else if (name == QLatin1String("Star")) {
+ data.insert(QStringLiteral("name"), QStringLiteral("Star"));
+ data.insert(QStringLiteral("sourcepath"), QStringLiteral("Star"));
+ data.insert(QStringLiteral("material"), QStringLiteral("Basic Texture"));
+ data.insert(QStringLiteral("position"),
+ QVariant::fromValue<QVector3D>(QVector3D(100, -150, 500)));
+ createElement(QStringLiteral("Scene.Layer"), QStringLiteral("Slide1"), data);
+ } else {
+ QVERIFY(false);
+ }
+ }
+ });
+
+ // Create mesh after start
+ QTimer::singleShot(1000, [&]() {
+ m_presentation->createMesh(QStringLiteral("Star"), star);
+ m_createdMeshes << QStringLiteral("Star");
+ });
+
+ QTimer::singleShot(3000, [&]() {
+ m_presentation->deleteElement(QStringLiteral("Scene.Layer.Star"));
+ m_presentation->deleteMesh(QStringLiteral("Star"));
+ m_createdMeshes.removeOne(QStringLiteral("Star"));
+ });
+
+ QVERIFY(spyExited.wait(20000));
+ QCOMPARE(spyMeshCreated.count(), 2);
+ QCOMPARE(spyElemCreated.count(), 2);
+ const QStringList createdMeshes = m_presentation->createdMeshes();
+ QCOMPARE(createdMeshes.size(), m_createdMeshes.size());
+ for (const auto &name : createdMeshes)
+ QVERIFY(m_createdMeshes.contains(name));
+ deleteCreated();
+ QTest::qWait(200); // Extra wait to verify slide change visually
+}
+
+void tst_qt3dsviewer::testMouseEvents()
+{
+ m_viewer->show();
+ QTest::qWait(1000);
+
+ QSignalSpy spyEvents(m_studio3DItem,
+ SIGNAL(ignoredEventsChanged()));
+ QSignalSpy spyExited(m_presentation,
+ SIGNAL(slideExited(const QString &, unsigned int, const QString &)));
+
+ QCOMPARE(spyEvents.count(), 0);
+ QCOMPARE(spyExited.count(), 0);
+
+ // Ignore mouse, so slide doesn't change
+ m_studio3DItem->setProperty("ignoredEvents", 1);
+ QTest::mousePress(m_viewer, Qt::LeftButton);
+ QTest::qWait(1000);
+ QTest::mouseRelease(m_viewer, Qt::LeftButton);
+ QCOMPARE(spyEvents.count(), 1);
+ QCOMPARE(spyExited.count(), 0);
+
+ // Enable mouse, clicking switches slide
+ m_studio3DItem->setProperty("ignoredEvents", 0);
+ QTest::mousePress(m_viewer, Qt::LeftButton);
+ QTest::qWait(1000);
+ QTest::mouseRelease(m_viewer, Qt::LeftButton);
+ QCOMPARE(spyEvents.count(), 2);
+ QCOMPARE(spyExited.count(), 1);
+}
+
+void tst_qt3dsviewer::deleteCreated()
+{
+ m_presentation->deleteElements(m_createdElements);
+ m_presentation->deleteMaterials(m_createdMaterials);
+ m_presentation->deleteMeshes(m_createdMeshes);
+ m_createdElements.clear();
+ m_createdMaterials.clear();
+ m_createdMeshes.clear();
+ QVERIFY(m_presentation->createdElements().size() == 0);
+ QVERIFY(m_presentation->createdMaterials().size() == 0);
+ QVERIFY(m_presentation->createdMeshes().size() == 0);
+}
+
+void tst_qt3dsviewer::createElement(const QString &parentElementPath, const QString &slideName,
+ const QHash<QString, QVariant> &properties)
+{
+ m_createdElements << parentElementPath + QLatin1Char('.')
+ + properties[QStringLiteral("name")].toString();
+ m_presentation->createElement(parentElementPath, slideName, properties);
+}
+
+void tst_qt3dsviewer::createGeometries(Q3DSGeometry &pyramid, Q3DSGeometry &star)
+{
+ struct Vertex {
+ QVector3D position;
+ QVector3D normal;
+ QVector2D uv;
+ };
+
+ QVector<Vertex> vertices;
+
+ auto createVertex = [&](const QVector3D &xyz, const QVector3D &n, const QVector2D &uv) {
+ Vertex newVertex;
+ newVertex.position = xyz;
+ if (n.isNull())
+ newVertex.normal = xyz; // This is almost never the correct normal
+ else
+ newVertex.normal = n.normalized();
+ newVertex.uv = uv;
+ vertices.append(newVertex);
+ };
+
+ auto createTriangle = [&](const QVector3D &xyz1, const QVector2D &uv1,
+ const QVector3D &xyz2, const QVector2D &uv2,
+ const QVector3D &xyz3, const QVector2D &uv3) {
+ QVector3D n;
+ n = QVector3D::crossProduct(xyz2 - xyz1, xyz3 - xyz1).normalized();
+
+ createVertex(xyz1, n, uv1);
+ createVertex(xyz2, n, uv2);
+ createVertex(xyz3, n, uv3);
+ };
+
+ // Pyramid (no index buffer)
+ {
+ QVector3D xyz[5] = {{0, 0, 50}, {50, 50, -50}, {50, -50, -50}, {-50, -50, -50},
+ {-50, 50, -50}};
+ QVector2D uv[4] = {{1, 1}, {1, 0}, {0, 0}, {0, 1}};
+ createTriangle(xyz[0], uv[0], xyz[1], uv[1], xyz[2], uv[2]);
+ createTriangle(xyz[0], uv[0], xyz[2], uv[1], xyz[3], uv[2]);
+ createTriangle(xyz[0], uv[0], xyz[3], uv[1], xyz[4], uv[2]);
+ createTriangle(xyz[0], uv[0], xyz[4], uv[1], xyz[1], uv[2]);
+ createTriangle(xyz[1], uv[0], xyz[4], uv[2], xyz[3], uv[1]);
+ createTriangle(xyz[1], uv[0], xyz[3], uv[3], xyz[2], uv[2]);
+
+ QByteArray vertexBuffer(reinterpret_cast<const char *>(vertices.constData()),
+ vertices.size() * int(sizeof(Vertex)));
+
+ pyramid.clear();
+ pyramid.setVertexData(vertexBuffer);
+ pyramid.addAttribute(Q3DSGeometry::Attribute::PositionSemantic);
+ pyramid.addAttribute(Q3DSGeometry::Attribute::NormalSemantic);
+ pyramid.addAttribute(Q3DSGeometry::Attribute::TexCoordSemantic);
+ }
+
+ vertices.clear();
+
+ // Star (using index buffer)
+ {
+ // Note: Since faces share vertices, the normals on the vertices are not correct
+ // for any face, leading to weird lighting behavior
+ createVertex({0, 150, 0}, {}, {0.5f, 1});
+ createVertex({50, 50, -50}, {}, {0.66f, 0.66f});
+ createVertex({150, 0, 0}, {}, {1, 0.5f});
+ createVertex({50, -50, -50}, {}, {0.66f, 0.33f});
+ createVertex({0, -150, 0}, {}, {0.5f, 0});
+ createVertex({-50, -50, -50}, {}, {0.33f, 0.33f});
+ createVertex({-150, 0, 0}, {}, {0, 0.5f});
+ createVertex({-50, 50, -50}, {}, {0.33f, 0.66f});
+ createVertex({50, 50, 50}, {}, {0.66f, 0.66f});
+ createVertex({50, -50, 50}, {}, {0.66f, 0.33f});
+ createVertex({-50, -50, 50}, {}, {0.33f, 0.33f});
+ createVertex({-50, 50, 50}, {}, {0.33f, 0.66f});
+
+ QVector<quint16> indices = {
+ 0, 1, 8, 0, 7, 1, 0, 11, 7, 0, 8, 11, // Top pyramid
+ 2, 1, 3, 2, 3, 9, 2, 9, 8, 2, 8, 1, // Right pyramid
+ 4, 3, 5, 4, 5, 10, 4, 10, 9, 4, 9, 3, // Bottom pyramid
+ 6, 5, 7, 6, 7, 11, 6, 11, 10, 6, 10, 5, // Left pyramid
+ 1, 7, 5, 1, 5, 3, // Front center rect
+ 8, 10, 11, 8, 9, 10 // Back center rect
+ };
+
+ QByteArray vertexBuffer(reinterpret_cast<const char *>(vertices.constData()),
+ vertices.size() * int(sizeof(Vertex)));
+ QByteArray indexBuffer(reinterpret_cast<const char *>(indices.constData()),
+ indices.size() * int(sizeof(quint16)));
+
+ Q3DSGeometry::Attribute indexAtt;
+ indexAtt.semantic = Q3DSGeometry::Attribute::IndexSemantic;
+ indexAtt.componentType = Q3DSGeometry::Attribute::ComponentType::U16Type;
+
+ star.clear();
+ star.setVertexData(vertexBuffer);
+ star.setIndexData(indexBuffer);
+ star.addAttribute(Q3DSGeometry::Attribute::PositionSemantic);
+ star.addAttribute(Q3DSGeometry::Attribute::NormalSemantic);
+ star.addAttribute(Q3DSGeometry::Attribute::TexCoordSemantic);
+ star.addAttribute(indexAtt);
+ }
+}
+
+QTEST_MAIN(tst_qt3dsviewer)
diff --git a/tests/auto/viewer/tst_qt3dsviewer.h b/tests/auto/viewer/tst_qt3dsviewer.h
new file mode 100644
index 0000000..3d1f947
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TST_QT3DSVIEWER
+#define TST_QT3DSVIEWER
+
+#include <QtTest/QtTest>
+#include <QtTest/QSignalSpy>
+#include <QtQuick/QQuickView>
+#include <QtStudio3D/q3dspresentation.h>
+#include <QtStudio3D/q3dsviewersettings.h>
+
+class tst_qt3dsviewer : public QObject
+{
+ Q_OBJECT
+public:
+ tst_qt3dsviewer()
+ {
+ }
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void testEmpty();
+ void testLoading();
+ void testSlides();
+ void testFrameUpdates();
+ void testSettings();
+ void testCreateElement();
+ void testCreateMaterial();
+ void testCreateMesh();
+ void testMouseEvents();
+
+private:
+ void deleteCreated();
+ void createElement(const QString &parentElementPath, const QString &slideName,
+ const QHash<QString, QVariant> &properties);
+ void createGeometries(Q3DSGeometry &pyramid, Q3DSGeometry &star);
+
+ QQuickView *m_viewer = nullptr;
+ QObject *m_studio3DItem = nullptr;
+ Q3DSPresentation *m_presentation = nullptr;
+ Q3DSViewerSettings *m_settings = nullptr;
+ QStringList m_createdElements;
+ QStringList m_createdMaterials;
+ QStringList m_createdMeshes;
+ bool m_ignoreError = false;
+
+};
+
+#endif // TST_QT3DSVIEWER
diff --git a/tests/auto/viewer/tst_qt3dsviewer.qml b/tests/auto/viewer/tst_qt3dsviewer.qml
new file mode 100644
index 0000000..e65a49d
--- /dev/null
+++ b/tests/auto/viewer/tst_qt3dsviewer.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtStudio3D.OpenGL 2.4
+
+Studio3D {
+ id: studio3D
+ width: 800
+ height: 800
+ Presentation {
+ source: "qrc:/scenes/simple_cube_animation/simple_cube_animation.uia"
+ }
+ ViewerSettings {
+ }
+}
diff --git a/tests/auto/viewer/viewer.pro b/tests/auto/viewer/viewer.pro
new file mode 100644
index 0000000..9a8da77
--- /dev/null
+++ b/tests/auto/viewer/viewer.pro
@@ -0,0 +1,21 @@
+TEMPLATE = app
+CONFIG += testcase
+include($$PWD/../../../commoninclude.pri)
+
+TARGET = tst_qt3dsviewer
+QT += testlib gui quick studio3d
+RESOURCES += viewer.qrc
+
+HEADERS += \
+ tst_qt3dsviewer.h
+
+SOURCES += \
+ tst_qt3dsviewer.cpp
+
+LIBS += \
+ -lqt3dsopengl$$qtPlatformTargetSuffix() \
+ -lqt3dsqmlstreamer$$qtPlatformTargetSuffix()
+
+ANDROID_EXTRA_LIBS = \
+ libqt3dsopengl.so \
+ libqt3dsqmlstreamer.so
diff --git a/tests/auto/viewer/viewer.qrc b/tests/auto/viewer/viewer.qrc
new file mode 100644
index 0000000..dcdddbe
--- /dev/null
+++ b/tests/auto/viewer/viewer.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/">
+ <file>../../scenes/simple_cube_animation/simple_cube_animation.uia</file>
+ <file>../../scenes/simple_cube_animation/presentations/simple_cube_animation.uip</file>
+ <file>../../scenes/simple_cube_animation/materials/Basic Green.materialdef</file>
+ <file>../../scenes/simple_cube_animation/materials/Basic Red.materialdef</file>
+ <file>../../scenes/simple_cube_animation/materials/Basic Blue.materialdef</file>
+ <file>../../scenes/simple_cube_animation/materials/Basic Texture.materialdef</file>
+ <file>../../scenes/simple_cube_animation/materials/Copper.materialdef</file>
+ <file>../../scenes/simple_cube_animation/materials/copper.shader</file>
+ <file>../../scenes/simple_cube_animation/maps/materials/shadow.png</file>
+ <file>../../scenes/simple_cube_animation/maps/materials/spherical_checker.png</file>
+ <file>../../scenes/simple_cube_animation/maps/QT-symbol.png</file>
+ <file>tst_qt3dsviewer.qml</file>
+ </qresource>
+</RCC>
diff --git a/tests/scenes/customvertex/customvertex.uia b/tests/scenes/customvertex/customvertex.uia
new file mode 100644
index 0000000..8448810
--- /dev/null
+++ b/tests/scenes/customvertex/customvertex.uia
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='utf-8'?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="customvertex">
+ <presentation id="customvertex" src="presentations/customvertex.uip"/>
+ </assets>
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Initial">
+ <enter>
+ <goto-slide rel="next" element="main:Scene"/>
+ </enter>
+ </state>
+ </visual-states>
+ </statemachine>
+</application>
diff --git a/tests/scenes/customvertex/materials/simple.shader b/tests/scenes/customvertex/materials/simple.shader
new file mode 100644
index 0000000..bdbd21e
--- /dev/null
+++ b/tests/scenes/customvertex/materials/simple.shader
@@ -0,0 +1,29 @@
+<Material name="simple" version="1.0">
+ <MetaData>
+ <Property formalName="Scale" name="scale" type="Vector" default="1 1 1" stage="vertex" category="Material" />
+ <Property formalName="Color" name="color" type="Color" default="1 1 1" stage="fragment" category="Material" />
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <VertexShader>
+ attribute vec3 attr_pos;
+ uniform mat4 modelViewProjection;
+
+ void main() {
+ gl_Position = modelViewProjection * vec4(attr_pos * scale, 1.0);
+ }
+ </VertexShader>
+ <FragmentShader>
+ out vec4 fragColor;
+ void main() {
+ fragColor = vec4(color.rgb, 1.0);
+ }
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes>
+ <Pass>
+ </Pass>
+</Passes>
+</Material>
+
diff --git a/tests/scenes/customvertex/presentations/customvertex.uip b/tests/scenes/customvertex/presentations/customvertex.uip
new file mode 100644
index 0000000..eba06da
--- /dev/null
+++ b/tests/scenes/customvertex/presentations/customvertex.uip
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="5" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="1920" presentationHeight="1080" maintainAspect="False" preferKtx="False" >
+ <CustomColors count="16" >#7391ff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Classes >
+ <CustomMaterial id="simple" name="simple" sourcepath="../materials/simple.shader" />
+ </Classes>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" variants="" >
+ <Camera id="Camera" />
+ <Light id="Light" />
+ <Model id="Sphere" >
+ <CustomMaterial id="simple_001" class="#simple" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" disabledepthprepass="True" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" />
+ <State id="Scene-Slide1" name="Slide1" >
+ <Add ref="#Sphere" name="Sphere" position="0 0 0" sourcepath="#Sphere" />
+ <Add ref="#simple_001" name="Material" color="0.333333 0.666667 0" scale="1 2 1" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/simple_cube_animation/maps/QT-symbol.png b/tests/scenes/simple_cube_animation/maps/QT-symbol.png
new file mode 100644
index 0000000..752a2e2
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/maps/QT-symbol.png
Binary files differ
diff --git a/tests/scenes/simple_cube_animation/maps/materials/shadow.png b/tests/scenes/simple_cube_animation/maps/materials/shadow.png
new file mode 100644
index 0000000..599b1cc
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/maps/materials/shadow.png
Binary files differ
diff --git a/tests/scenes/simple_cube_animation/maps/materials/spherical_checker.png b/tests/scenes/simple_cube_animation/maps/materials/spherical_checker.png
new file mode 100644
index 0000000..e42394d
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/maps/materials/spherical_checker.png
Binary files differ
diff --git a/tests/scenes/simple_cube_animation/materials/Basic Blue.materialdef b/tests/scenes/simple_cube_animation/materials/Basic Blue.materialdef
new file mode 100644
index 0000000..c35d47b
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/Basic Blue.materialdef
@@ -0,0 +1,25 @@
+<MaterialData version="1.0">
+ <Property name="shaderlighting">Pixel</Property>
+ <Property name="blendmode">Normal</Property>
+ <Property name="diffuse">0 0.482353 1 1</Property>
+ <Property name="specularamount">0</Property>
+ <Property name="specularroughness">0</Property>
+ <Property name="opacity">100</Property>
+ <Property name="emissivecolor">1 1 1 1</Property>
+ <Property name="emissivepower">0</Property>
+ <Property name="bumpamount">0.5</Property>
+ <Property name="displaceamount">20</Property>
+ <Property name="translucentfalloff">1</Property>
+ <Property name="diffuselightwrap">0</Property>
+ <Property name="specularmodel">Default</Property>
+ <Property name="speculartint">1 1 1 1</Property>
+ <Property name="ior">1.5</Property>
+ <Property name="fresnelPower">0</Property>
+ <Property name="vertexcolors">False</Property>
+ <Property name="sourcepath"></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Material</Property>
+ <Property name="name"><![CDATA[materials/Basic Blue]]></Property>
+ <Property name="path"><![CDATA[C:/dev/q3dstudio/qt3dstudio/tests/scenes/simple_cube_animation/materials/Basic Blue.materialdef]]></Property>
+</MaterialData> \ No newline at end of file
diff --git a/tests/scenes/simple_cube_animation/materials/Basic Green.materialdef b/tests/scenes/simple_cube_animation/materials/Basic Green.materialdef
new file mode 100644
index 0000000..273a348
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/Basic Green.materialdef
@@ -0,0 +1,25 @@
+<MaterialData version="1.0">
+ <Property name="shaderlighting">Pixel</Property>
+ <Property name="blendmode">Normal</Property>
+ <Property name="diffuse">0.180392 1 0 1</Property>
+ <Property name="specularamount">0</Property>
+ <Property name="specularroughness">0</Property>
+ <Property name="opacity">100</Property>
+ <Property name="emissivecolor">1 1 1 1</Property>
+ <Property name="emissivepower">0</Property>
+ <Property name="bumpamount">0.5</Property>
+ <Property name="displaceamount">20</Property>
+ <Property name="translucentfalloff">1</Property>
+ <Property name="diffuselightwrap">0</Property>
+ <Property name="specularmodel">Default</Property>
+ <Property name="speculartint">1 1 1 1</Property>
+ <Property name="ior">1.5</Property>
+ <Property name="fresnelPower">0</Property>
+ <Property name="vertexcolors">False</Property>
+ <Property name="sourcepath"></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Material</Property>
+ <Property name="name"><![CDATA[materials/Basic Green]]></Property>
+ <Property name="path"><![CDATA[C:/dev/q3dstudio/qt3dstudio/tests/scenes/simple_cube_animation/materials/Basic Green.materialdef]]></Property>
+</MaterialData> \ No newline at end of file
diff --git a/tests/scenes/simple_cube_animation/materials/Basic Red.materialdef b/tests/scenes/simple_cube_animation/materials/Basic Red.materialdef
new file mode 100644
index 0000000..38b8eb7
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/Basic Red.materialdef
@@ -0,0 +1,25 @@
+<MaterialData version="1.0">
+ <Property name="shaderlighting">Pixel</Property>
+ <Property name="blendmode">Normal</Property>
+ <Property name="diffuse">1 0 0.0156863 1</Property>
+ <Property name="specularamount">0</Property>
+ <Property name="specularroughness">0</Property>
+ <Property name="opacity">100</Property>
+ <Property name="emissivecolor">1 1 1 1</Property>
+ <Property name="emissivepower">0</Property>
+ <Property name="bumpamount">0.5</Property>
+ <Property name="displaceamount">20</Property>
+ <Property name="translucentfalloff">1</Property>
+ <Property name="diffuselightwrap">0</Property>
+ <Property name="specularmodel">Default</Property>
+ <Property name="speculartint">1 1 1 1</Property>
+ <Property name="ior">1.5</Property>
+ <Property name="fresnelPower">0</Property>
+ <Property name="vertexcolors">False</Property>
+ <Property name="sourcepath"></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Material</Property>
+ <Property name="name"><![CDATA[materials/Basic Red]]></Property>
+ <Property name="path"><![CDATA[C:/dev/q3dstudio/qt3dstudio/tests/scenes/simple_cube_animation/materials/Basic Red.materialdef]]></Property>
+</MaterialData> \ No newline at end of file
diff --git a/tests/scenes/simple_cube_animation/materials/Basic Texture.materialdef b/tests/scenes/simple_cube_animation/materials/Basic Texture.materialdef
new file mode 100644
index 0000000..4defa98
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/Basic Texture.materialdef
@@ -0,0 +1,63 @@
+<MaterialData version="1.0">
+ <Property name="shaderlighting">Pixel</Property>
+ <Property name="blendmode">Normal</Property>
+ <Property name="diffuse">0.752941 0.756863 1 1</Property>
+ <Property name="diffusemap"><![CDATA[./maps/materials/spherical_checker.png]]></Property>
+ <Property name="diffusemap2"><![CDATA[./maps/QT-symbol.png]]></Property>
+ <Property name="specularamount">0</Property>
+ <Property name="specularroughness">0</Property>
+ <Property name="opacity">100</Property>
+ <Property name="emissivecolor">1 1 1 1</Property>
+ <Property name="emissivepower">0</Property>
+ <Property name="bumpamount">0.5</Property>
+ <Property name="displaceamount">20</Property>
+ <Property name="translucentfalloff">1</Property>
+ <Property name="diffuselightwrap">0</Property>
+ <Property name="specularmodel">Default</Property>
+ <Property name="speculartint">1 1 1 1</Property>
+ <Property name="ior">1.5</Property>
+ <Property name="fresnelPower">0</Property>
+ <Property name="vertexcolors">False</Property>
+ <Property name="sourcepath"></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Material</Property>
+ <Property name="name"><![CDATA[materials/Basic Texture]]></Property>
+ <Property name="path"><![CDATA[C:/dev/qt/NDD/qt3ds2/tests/scenes/simple_cube_animation/materials/Basic Texture.materialdef]]></Property>
+ <TextureData name="diffusemap">
+ <Property name="scaleu">1</Property>
+ <Property name="scalev">1</Property>
+ <Property name="mappingmode">UV Mapping</Property>
+ <Property name="tilingmodehorz">Tiled</Property>
+ <Property name="tilingmodevert">Tiled</Property>
+ <Property name="rotationuv">0</Property>
+ <Property name="positionu">0</Property>
+ <Property name="positionv">0</Property>
+ <Property name="pivotu">0</Property>
+ <Property name="pivotv">0</Property>
+ <Property name="subpresentation"></Property>
+ <Property name="sourcepath"><![CDATA[./maps/materials/spherical_checker.png]]></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Image</Property>
+ <Property name="name"><![CDATA[Image]]></Property>
+ </TextureData>
+ <TextureData name="diffusemap2">
+ <Property name="scaleu">2</Property>
+ <Property name="scalev">3</Property>
+ <Property name="mappingmode">UV Mapping</Property>
+ <Property name="tilingmodehorz">Tiled</Property>
+ <Property name="tilingmodevert">Tiled</Property>
+ <Property name="rotationuv">0</Property>
+ <Property name="positionu">0</Property>
+ <Property name="positionv">0</Property>
+ <Property name="pivotu">0</Property>
+ <Property name="pivotv">0</Property>
+ <Property name="subpresentation"></Property>
+ <Property name="sourcepath"><![CDATA[./maps/QT-symbol.png]]></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">Image</Property>
+ <Property name="name"><![CDATA[Image]]></Property>
+ </TextureData>
+</MaterialData> \ No newline at end of file
diff --git a/tests/scenes/simple_cube_animation/materials/Copper.materialdef b/tests/scenes/simple_cube_animation/materials/Copper.materialdef
new file mode 100644
index 0000000..7688098
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/Copper.materialdef
@@ -0,0 +1,14 @@
+<MaterialData version="1.0">
+ <Property name="uEnvironmentTexture" type="Texture"><![CDATA[./maps/materials/spherical_checker.png]]></Property>
+ <Property name="uEnvironmentMappingEnabled">True</Property>
+ <Property name="uBakedShadowTexture" type="Texture"><![CDATA[./maps/materials/shadow.png]]></Property>
+ <Property name="uShadowMappingEnabled">False</Property>
+ <Property name="roughness">0</Property>
+ <Property name="metal_color">0.807843 0.45098 0.211765 1</Property>
+ <Property name="sourcepath"><![CDATA[./materials/copper.shader]]></Property>
+ <Property name="importid"></Property>
+ <Property name="importfile"></Property>
+ <Property name="type">CustomMaterial</Property>
+ <Property name="name"><![CDATA[materials/Copper]]></Property>
+ <Property name="path"><![CDATA[C:/dev/qt/NDD/qt3ds2/tests/scenes/simple_cube_animation/materials/Copper.materialdef]]></Property>
+</MaterialData> \ No newline at end of file
diff --git a/tests/scenes/simple_cube_animation/materials/copper.shader b/tests/scenes/simple_cube_animation/materials/copper.shader
new file mode 100644
index 0000000..cf9e1ad
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/materials/copper.shader
@@ -0,0 +1,178 @@
+<Material name="copper" version="1.0">
+ <MetaData >
+ <Property formalName="Environment Map" name="uEnvironmentTexture" description="Environment texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="environment" default="./maps/materials/spherical_checker.png" category="Material"/>
+ <Property formalName="Enable Environment" name="uEnvironmentMappingEnabled" description="Enable environment mapping" type="Boolean" default="True" category="Material"/>
+ <Property formalName="Baked Shadow Map" name="uBakedShadowTexture" description="Baked shadow texture for the material" type="Texture" filter="linear" minfilter="linearMipmapLinear" clamp="repeat" usage="shadow" default="./maps/materials/shadow.png" category="Material"/>
+ <Property formalName="Shadow Mapping" name="uShadowMappingEnabled" description="Enable shadow mapping" type="Boolean" default="False" category="Material"/>
+ <Property formalName="Roughness" name="roughness" type="Float" min="0.000000" max="1.000000" default="0.000000" description="Roughness of the material.\n0 = fully specular\n1 = fully diffuse" category="Material"/>
+ <Property formalName="Metal Color" name="metal_color" type="Color" default="0.805 0.395 0.305" description="Color of the material" category="Material"/>
+ </MetaData>
+ <Shaders type="GLSL" version="330">
+ <Shader>
+ <Shared> </Shared>
+<VertexShader>
+ </VertexShader>
+ <FragmentShader>
+
+// add enum defines
+#define scatter_reflect 0
+#define scatter_transmit 1
+#define scatter_reflect_transmit 2
+
+#define QT3DS_ENABLE_UV0 1
+#define QT3DS_ENABLE_WORLD_POSITION 1
+#define QT3DS_ENABLE_TEXTAN 1
+#define QT3DS_ENABLE_BINORMAL 0
+
+#include "vertexFragmentBase.glsllib"
+
+// set shader output
+out vec4 fragColor;
+
+// add structure defines
+struct layer_result
+{
+ vec4 base;
+ vec4 layer;
+ mat3 tanFrame;
+};
+
+
+// temporary declarations
+ vec4 tmpShadowTerm;
+
+layer_result layers[1];
+
+#include "SSAOCustomMaterial.glsllib"
+#include "sampleLight.glsllib"
+#include "sampleProbe.glsllib"
+#include "sampleArea.glsllib"
+#include "square.glsllib"
+#include "calculateRoughness.glsllib"
+#include "evalBakedShadowMap.glsllib"
+#include "evalEnvironmentMap.glsllib"
+#include "luminance.glsllib"
+#include "microfacetBSDF.glsllib"
+#include "physGlossyBSDF.glsllib"
+#include "simpleGlossyBSDF.glsllib"
+#include "fresnelLayer.glsllib"
+
+bool evalTwoSided()
+{
+ return( false );
+}
+
+vec3 computeFrontMaterialEmissive()
+{
+ return( vec3( 0, 0, 0 ) );
+}
+
+void computeFrontLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += tmpShadowTerm * microfacetBSDF( layers[0].tanFrame, lightDir, viewDir, lightSpecular, materialIOR, roughness, roughness, scatter_reflect );
+
+#endif
+}
+
+void computeFrontAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += tmpShadowTerm * lightSpecular * sampleAreaGlossy( layers[0].tanFrame, varWorldPos, lightIdx, viewDir, roughness, roughness );
+
+#endif
+}
+
+void computeFrontLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += tmpShadowTerm * microfacetSampledBSDF( layers[0].tanFrame, viewDir, roughness, roughness, scatter_reflect );
+
+#else
+ layers[0].base += tmpShadowTerm * vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += tmpShadowTerm * sampleGlossyAniso( layers[0].tanFrame, viewDir, roughness, roughness );
+
+#endif
+}
+
+vec3 computeBackMaterialEmissive()
+{
+ return( vec3(0, 0, 0) );
+}
+
+void computeBackLayerColor( in vec3 normal, in vec3 lightDir, in vec3 viewDir, in vec3 lightDiffuse, in vec3 lightSpecular, in float materialIOR, float aoFactor )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackAreaColor( in int lightIdx, in vec4 lightDiffuse, in vec4 lightSpecular )
+{
+#if QT3DS_ENABLE_CG_LIGHTING
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+void computeBackLayerEnvironment( in vec3 normal, in vec3 viewDir, float aoFactor )
+{
+#if !QT3DS_ENABLE_LIGHT_PROBE
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#else
+ layers[0].base += vec4( 0.0, 0.0, 0.0, 1.0 );
+ layers[0].layer += vec4( 0.0, 0.0, 0.0, 1.0 );
+#endif
+}
+
+float computeIOR()
+{
+ return( false ? 1.0 : luminance( vec3( 1, 1, 1 ) ) );
+}
+
+float evalCutout()
+{
+ return( 1.000000 );
+}
+
+vec3 computeNormal()
+{
+ return( normal );
+}
+
+void computeTemporaries()
+{
+ tmpShadowTerm = evalBakedShadowMap( texCoord0 );
+}
+
+vec4 computeLayerWeights( in float alpha )
+{
+ vec4 color;
+ color = fresnelLayer( normal, vec3( 25.65, 25.65, 25.65 ), 1.000000, metal_color.rgb, layers[0].layer, layers[0].base, alpha );
+ return color;
+}
+
+
+void initializeLayerVariables(void)
+{
+ // clear layers
+ layers[0].base = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].layer = vec4(0.0, 0.0, 0.0, 1.0);
+ layers[0].tanFrame = orthoNormalize( mat3( tangent, cross(normal, tangent), normal ) );
+}
+
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+<Passes >
+ <ShaderKey value="4"/>
+ <LayerKey count="1"/>
+ <Pass >
+ </Pass>
+</Passes>
+</Material>
diff --git a/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip b/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip
new file mode 100644
index 0000000..f8fae90
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/presentations/simple_cube_animation.uip
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<UIP version="6" >
+ <Project >
+ <ProjectSettings author="" company="" presentationWidth="600" presentationHeight="600" maintainAspect="False" preferKtx="False" >
+ <CustomColors count="16" >#7391ff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff #ffffff</CustomColors>
+ </ProjectSettings>
+ <Graph >
+ <Scene id="Scene" >
+ <Layer id="Layer" variants="" >
+ <Camera id="Camera" />
+ <Light id="Light" >
+ <Model id="Sphere" variants="" >
+ <Material id="Default_animatable" />
+ </Model>
+ </Light>
+ <Model id="Cube" variants="" >
+ <Material id="Basic Green_animatable" />
+ </Model>
+ <Model id="Cube2" variants="" >
+ <Material id="Basic Red_animatable" />
+ </Model>
+ </Layer>
+ </Scene>
+ </Graph>
+ <Logic >
+ <State name="Master Slide" component="#Scene" >
+ <Add ref="#Layer" background="SolidColor" backgroundcolor="0.584314 0.0941176 0.34902 1" />
+ <Add ref="#Camera" />
+ <Add ref="#Light" brightness="400" lighttype="Point" >
+ <AnimationTrack property="position.x" type="EaseInOut" >0 -341.785 100 100 5 269.972 100 100</AnimationTrack>
+ <AnimationTrack property="position.y" type="EaseInOut" >0 0 100 100 5 0 100 100</AnimationTrack>
+ <AnimationTrack property="position.z" type="EaseInOut" >0 0 100 100 5 0 100 100</AnimationTrack>
+ </Add>
+ <State id="Scene-Slide1" name="Slide1" playmode="Play Through To..." >
+ <Set ref="#Layer" endtime="5000" >
+ <Action id="Layer-Action" eyeball="True" triggerObject="#Scene" event="onPressureDown" targetObject="#Scene" handler="Next Slide" />
+ </Set>
+ <Set ref="#Camera" endtime="5000" />
+ <Set ref="#Light" endtime="5000" />
+ <Add ref="#Sphere" name="Sphere" endtime="5000" scale="0.1 0.1 0.1" sourcepath="#Sphere" />
+ <Add ref="#Default_animatable" name="Default_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 1 0 1" diffuselightwrap="0" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="None" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" />
+ <Add ref="#Cube" name="Cube" endtime="5000" position="-458.877 -70.3589 600" sourcepath="#Cube" >
+ <AnimationTrack property="rotation.x" type="EaseInOut" >0 0 100 100 1 0 100 100 4 0 100 100 5 90 100 100 7 90 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.y" type="EaseInOut" >0 0 100 100 1 0 100 100 4 90 100 100 5 0 100 100 7 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="rotation.z" type="EaseInOut" >0 0 100 100 1 -90 100 100 4 -90 100 100 5 -90 100 100 7 0 100 100 10 0 100 100</AnimationTrack>
+ <AnimationTrack property="scale.x" type="EaseInOut" >0 1 100 100 2 1.5 100 100 3 1.5 100 100 6 2 100 100 7 1 100 100 8 1 100 100 9 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.y" type="EaseInOut" >0 1 100 100 2 1.5 100 100 3 1.5 100 100 6 2 100 100 7 2 100 100 8 1 100 100 9 1 100 100</AnimationTrack>
+ <AnimationTrack property="scale.z" type="EaseInOut" >0 1 100 100 2 1 100 100 3 1.5 100 100 6 2 100 100 7 2 100 100 8 2 100 100 9 1 100 100</AnimationTrack>
+ </Add>
+ <Add ref="#Basic Green_animatable" name="Basic Green_animatable" blendmode="Normal" bumpamount="0.5" diffuse="0.180392 1 0 1" diffuselightwrap="0" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" />
+ </State>
+ <State id="Scene-Slide2" name="Slide2" playmode="Play Through To..." playthroughto="Previous" >
+ <Set ref="#Layer" endtime="5000" />
+ <Set ref="#Camera" endtime="5000" />
+ <Set ref="#Light" endtime="5000" />
+ <Add ref="#Cube2" name="Cube2" endtime="5000" position="-401.836 -18.4752 600" scale="3 3 3" sourcepath="#Cube" />
+ <Add ref="#Basic Red_animatable" name="Basic Red_animatable" blendmode="Normal" bumpamount="0.5" diffuse="1 0 0.0156863 1" diffuselightwrap="0" displaceamount="20" emissivecolor="1 1 1 1" emissivepower="0" fresnelPower="0" importfile="" importid="" ior="1.5" opacity="100" shaderlighting="Pixel" sourcepath="" specularamount="0" specularmodel="Default" specularroughness="0" speculartint="1 1 1 1" translucentfalloff="1" type="Material" vertexcolors="False" />
+ </State>
+ </State>
+ </Logic>
+ </Project>
+</UIP>
diff --git a/tests/scenes/simple_cube_animation/simple_cube_animation.uia b/tests/scenes/simple_cube_animation/simple_cube_animation.uia
new file mode 100644
index 0000000..ca2d770
--- /dev/null
+++ b/tests/scenes/simple_cube_animation/simple_cube_animation.uia
@@ -0,0 +1,16 @@
+<?xml version='1.0' encoding='utf-8'?>
+<application xmlns="http://qt.io/qt3dstudio/uia">
+ <assets initial="simple_cube_animation">
+ <presentation id="simple_cube_animation" src="presentations/simple_cube_animation.uip"/>
+ <dataInput metadata="" name="newDataInput" type="Float"/>
+ </assets>
+ <statemachine ref="#logic">
+ <visual-states>
+ <state ref="Initial">
+ <enter>
+ <goto-slide rel="next" element="main:Scene"/>
+ </enter>
+ </state>
+ </visual-states>
+ </statemachine>
+</application>
diff --git a/tests/tests.pro b/tests/tests.pro
index 9671085..c458bbb 100644
--- a/tests/tests.pro
+++ b/tests/tests.pro
@@ -1 +1,4 @@
TEMPLATE = subdirs
+
+!package: SUBDIRS += \
+ auto