From ce4663c2659d9e1611a1647a9b3cd26da8a80604 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Tue, 8 Oct 2019 08:01:10 +0100 Subject: Clean up old property update code Remove useless includes, clear up commented out or unused code Change-Id: Id3382b16108d79f1e2522d43463c8d70aef8fcb2 Reviewed-by: Mike Krus --- tests/auto/animation/animationclip/tst_animationclip.cpp | 2 -- tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp | 2 -- tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp | 1 - tests/auto/animation/skeleton/tst_skeleton.cpp | 1 - tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp | 2 -- tests/auto/input/action/tst_action.cpp | 1 - tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp | 2 -- tests/auto/input/axis/tst_axis.cpp | 1 - tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp | 1 - tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp | 2 -- tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp | 1 - tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp | 2 -- .../qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp | 1 - tests/auto/input/qaction/tst_qaction.cpp | 1 - tests/auto/input/qaxis/tst_qaxis.cpp | 1 - tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp | 1 - tests/auto/render/objectpicker/tst_objectpicker.cpp | 1 - tests/auto/render/raycaster/tst_raycaster.cpp | 1 - tests/auto/render/transform/tst_transform.cpp | 1 - 19 files changed, 25 deletions(-) (limited to 'tests') diff --git a/tests/auto/animation/animationclip/tst_animationclip.cpp b/tests/auto/animation/animationclip/tst_animationclip.cpp index 35df21a58..d28a8fc58 100644 --- a/tests/auto/animation/animationclip/tst_animationclip.cpp +++ b/tests/auto/animation/animationclip/tst_animationclip.cpp @@ -31,9 +31,7 @@ #include #include #include -#include #include -#include #include #include diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index bb95fe979..fb741050b 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -44,7 +43,6 @@ #include #include #include -#include #include "qbackendnodetester.h" class tst_BlendedClipAnimator : public Qt3DCore::QBackendNodeTester diff --git a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp index 274144d3e..00130add3 100644 --- a/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp +++ b/tests/auto/animation/qanimationcliploader/tst_qanimationcliploader.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/auto/animation/skeleton/tst_skeleton.cpp b/tests/auto/animation/skeleton/tst_skeleton.cpp index 99acf0b43..d9b209194 100644 --- a/tests/auto/animation/skeleton/tst_skeleton.cpp +++ b/tests/auto/animation/skeleton/tst_skeleton.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp index 48ac4b3fe..94f02bc1e 100644 --- a/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp +++ b/tests/auto/input/abstractaxisinput/tst_abstractaxisinput.cpp @@ -30,11 +30,9 @@ #include #include #include -#include #include #include #include -#include #include "testdevice.h" class DummyAxisInput : public Qt3DInput::QAbstractAxisInput diff --git a/tests/auto/input/action/tst_action.cpp b/tests/auto/input/action/tst_action.cpp index 6b8b11b80..cc40cef2f 100644 --- a/tests/auto/input/action/tst_action.cpp +++ b/tests/auto/input/action/tst_action.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp index 0bdaadc46..6f91ce337 100644 --- a/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp +++ b/tests/auto/input/analogaxisinput/tst_analogaxisinput.cpp @@ -32,11 +32,9 @@ #include #include -#include #include #include #include -#include class tst_AnalogAxisInput: public Qt3DCore::QBackendNodeTester { diff --git a/tests/auto/input/axis/tst_axis.cpp b/tests/auto/input/axis/tst_axis.cpp index de9d5c553..ddd59b395 100644 --- a/tests/auto/input/axis/tst_axis.cpp +++ b/tests/auto/input/axis/tst_axis.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp index f7d7d32f1..f8d4adcd2 100644 --- a/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp +++ b/tests/auto/input/axisaccumulator/tst_axisaccumulator.cpp @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp index 5debe4d99..e315ed1dc 100644 --- a/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp +++ b/tests/auto/input/buttonaxisinput/tst_buttonaxisinput.cpp @@ -32,11 +32,9 @@ #include #include -#include #include #include #include -#include class tst_ButtonAxisInput: public Qt3DCore::QBackendNodeTester { diff --git a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp index 985ee1955..c5322eda6 100644 --- a/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp +++ b/tests/auto/input/loadproxydevicejob/tst_loadproxydevicejob.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include "qbackendnodetester.h" #include "testdeviceproxy.h" diff --git a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp index aaf46a54b..bd5da8e3f 100644 --- a/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp +++ b/tests/auto/input/physicaldeviceproxy/tst_physicaldeviceproxy.cpp @@ -32,9 +32,7 @@ #include #include #include -#include #include -#include #include "qbackendnodetester.h" #include "testdeviceproxy.h" #include "testpostmanarbiter.h" diff --git a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp index aef76cc0d..bbe184e0e 100644 --- a/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp +++ b/tests/auto/input/qabstractphysicaldeviceproxy/tst_qabstractphysicaldeviceproxy.cpp @@ -29,7 +29,6 @@ #include -#include #include #include #include "testdeviceproxy.h" diff --git a/tests/auto/input/qaction/tst_qaction.cpp b/tests/auto/input/qaction/tst_qaction.cpp index 8d097978f..13c4a2d83 100644 --- a/tests/auto/input/qaction/tst_qaction.cpp +++ b/tests/auto/input/qaction/tst_qaction.cpp @@ -27,7 +27,6 @@ ****************************************************************************/ #include -#include #include #include #include diff --git a/tests/auto/input/qaxis/tst_qaxis.cpp b/tests/auto/input/qaxis/tst_qaxis.cpp index 36d434c6a..9b3068442 100644 --- a/tests/auto/input/qaxis/tst_qaxis.cpp +++ b/tests/auto/input/qaxis/tst_qaxis.cpp @@ -27,7 +27,6 @@ ****************************************************************************/ #include -#include #include #include #include diff --git a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp index e4145ab7a..9f96cd845 100644 --- a/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp +++ b/tests/auto/input/qaxisaccumulator/tst_qaxisaccumulator.cpp @@ -27,7 +27,6 @@ ****************************************************************************/ #include -#include #include #include #include diff --git a/tests/auto/render/objectpicker/tst_objectpicker.cpp b/tests/auto/render/objectpicker/tst_objectpicker.cpp index 5fc988d47..24fa2159d 100644 --- a/tests/auto/render/objectpicker/tst_objectpicker.cpp +++ b/tests/auto/render/objectpicker/tst_objectpicker.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include "testpostmanarbiter.h" #include "testrenderer.h" diff --git a/tests/auto/render/raycaster/tst_raycaster.cpp b/tests/auto/render/raycaster/tst_raycaster.cpp index 72ef396d7..57a1bcf47 100644 --- a/tests/auto/render/raycaster/tst_raycaster.cpp +++ b/tests/auto/render/raycaster/tst_raycaster.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include "testpostmanarbiter.h" #include "testrenderer.h" diff --git a/tests/auto/render/transform/tst_transform.cpp b/tests/auto/render/transform/tst_transform.cpp index 476c47393..a3fcdb9c8 100644 --- a/tests/auto/render/transform/tst_transform.cpp +++ b/tests/auto/render/transform/tst_transform.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include "qbackendnodetester.h" #include "testrenderer.h" -- cgit v1.2.3 From 7eb01e9532f080bef539808c0eb5e7c65cf34048 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 27 Sep 2019 14:31:21 +0200 Subject: Split RenderCommand generation and uniform update In most cases, we can generate the RenderCommands once and reuse them in subsequent frames only updating the uniforms. We still have to copy the RenderCommands as the renderer renders while we start preparing the next frame. This is still faster than regenerating them entirely. Regenerating the entire commands will happen only when FrameGraph or Scene structure changes. That should rarely be happening on a per frame basis. Next step could be to look at how to only update commands for Entity with Parameters that have changed. Change-Id: I202870850a46fcd3946f81bffddb7027d192f374 Reviewed-by: Paul Lemire --- tests/auto/render/renderer/tst_renderer.cpp | 73 ++++++------ .../renderviewbuilder/tst_renderviewbuilder.cpp | 114 +++++++++---------- tests/auto/render/renderviews/tst_renderviews.cpp | 126 ++++++++++----------- 3 files changed, 151 insertions(+), 162 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index e1bf8dfd9..65309707c 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -160,6 +160,9 @@ private Q_SLOTS: const int layerCacheJobCount = 2; // filterEntityByLayerJob, // syncFilterEntityByLayerJob + + const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); // RenderViewBuilder renderViewJob, // syncRenderViewInitializationJob, @@ -167,20 +170,42 @@ private Q_SLOTS: // filterProximityJob, // setClearDrawBufferIndexJob, // frustumCullingJob, - // syncRenderCommandBuldingJob, - // syncRenderViewCommandBuilderJob + // syncRenderCommandUpdateJob, + // syncRenderViewCommandPostUpdateJob // n * (RenderViewCommandBuildJobs) // WHEN QVector jobs = renderer.renderBinJobs(); - // THEN + // THEN -> AllDirty + // (Renderer is not initialized so FilterCompatibleTechniqueJob + // and ShaderGathererJob are not added here) QCOMPARE(jobs.size(), + 1 + // EntityEnabledDirty + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // ExpandBoundingVolumeJob + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs 1 + // updateLevelOfDetailJob 1 + // cleanupJob 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1); // SyncLoadingJobs + 1 + // BufferGathererJob + 1 + // TexturesGathererJob + 1 + // UpdateEntityLayersJob + 1 + // LightGathererJob + 1 + // CacheLightJob + 1 + // RenderableEntityFilterJob + 1 + // CacheRenderableEntitiesJob + 1 + // ComputableEntityFilterJob + 1 + // CacheComputableEntitiesJob + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + layerCacheJobCount + + renderViewBuilderMaterialCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); @@ -197,6 +222,7 @@ private Q_SLOTS: 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + layerCacheJobCount); @@ -253,6 +279,7 @@ private Q_SLOTS: 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -274,6 +301,7 @@ private Q_SLOTS: 1 + // ExpandBoundingVolumeJob 1 + // RenderableEntityFilterPtr 1 + // SyncRenderableEntities + singleRenderViewCommandRebuildJobCount + singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -315,41 +343,6 @@ private Q_SLOTS: renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (Renderer is not initialized so FilterCompatibleTechniqueJob - // and ShaderGathererJob are not added here) - QCOMPARE(jobs.size(), - 1 + // EntityEnabledDirty - 1 + // WorldTransformJob - 1 + // UpdateWorldBoundingVolume - 1 + // UpdateShaderDataTransform - 1 + // ExpandBoundingVolumeJob - 1 + // CalculateBoundingVolumeJob - 1 + // UpdateMeshTriangleListJob - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // BufferGathererJob - 1 + // TexturesGathererJob - 1 + // UpdateEntityLayersJob - 1 + // LightGathererJob - 1 + // CacheLightJob - 1 + // RenderableEntityFilterJob - 1 + // CacheRenderableEntitiesJob - 1 + // ComputableEntityFilterJob - 1 + // CacheComputableEntitiesJob - singleRenderViewJobCount + - layerCacheJobCount + - renderViewBuilderMaterialCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - // Properly shutdown command thread renderer.shutdown(); } diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index 96d51a3a9..0fb1f5e24 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -224,29 +224,29 @@ private Q_SLOTS: QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), false); QVERIFY(!renderViewBuilder.renderViewJob().isNull()); QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncFrustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.syncPreFrustumCullingJob().isNull()); QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderViewInitializationJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); - QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), 0); + QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), 0); QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); // WHEN renderViewBuilder.prepareJobs(); // THEN - QVERIFY(!renderViewBuilder.syncRenderCommandBuildingJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewCommandBuildersJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewInitializationJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - QCOMPARE(renderViewBuilder.renderViewBuilderJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); } @@ -338,8 +338,8 @@ private Q_SLOTS: // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().constFirst().toStrongRef().data(), + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), renderViewBuilder.renderViewJob().data()); // Step 3 @@ -347,43 +347,43 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewInitializationJob().data()); + renderViewBuilder.syncRenderViewPostInitializationJob().data()); - QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); // Step 4 QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - QCOMPARE(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); + QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); // Step 5 - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderCommandBuildingJob().data()); + renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); } // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); } } { @@ -399,63 +399,63 @@ private Q_SLOTS: QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewInitializationJob()->dependencies().constFirst().toStrongRef().data(), + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), renderViewBuilder.renderViewJob().data()); // Step 3 QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3); QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewInitializationJob().data()); + renderViewBuilder.syncRenderViewPostInitializationJob().data()); - QCOMPARE(renderViewBuilder.syncFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { QCOMPARE(materialGatherer->dependencies().size(), 3); - QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob())); QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); } // Step 4 QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); - QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); // Step 5 - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderCommandBuildingJob().data()); + renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); } // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().size(), renderViewBuilder.renderViewBuilderJobs().size()); - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewBuilderJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewCommandBuildersJob()->dependencies().contains(renderViewBuilderJob)); + QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); } } } @@ -581,7 +581,7 @@ private Q_SLOTS: // WHEN renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewInitializationJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); // THEN QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); @@ -608,7 +608,7 @@ private Q_SLOTS: // WHEN renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewInitializationJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); // THEN QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); @@ -647,7 +647,7 @@ private Q_SLOTS: // WHEN renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncFrustumCullingJob()->run(); + renderViewBuilder.syncPreFrustumCullingJob()->run(); // THEN QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix()); @@ -676,7 +676,7 @@ private Q_SLOTS: renderViewBuilder.renderViewJob()->run(); renderViewBuilder.renderableEntityFilterJob()->run(); - renderViewBuilder.syncRenderViewInitializationJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); renderViewBuilder.filterEntityByLayerJob()->run(); QVector renderableEntity = renderViewBuilder.renderableEntityFilterJob()->filteredEntities(); diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index f38915bf8..17995659b 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -138,14 +138,14 @@ private Q_SLOTS: { // GIVEN RenderView renderView; - QVector rawCommands; + QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::BackToFront); for (int i = 0; i < 200; ++i) { - RenderCommand *c = new RenderCommand(); - c->m_depth = float(i); + RenderCommand c; + c.m_depth = float(i); rawCommands.push_back(c); } @@ -155,10 +155,10 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1)->m_depth > sortedCommands.at(j)->m_depth); + QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth); // RenderCommands are deleted by RenderView dtor } @@ -167,7 +167,7 @@ private Q_SLOTS: { // GIVEN RenderView renderView; - QVector rawCommands; + QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::Material); @@ -181,8 +181,8 @@ private Q_SLOTS: }; for (int i = 0; i < 20; ++i) { - RenderCommand *c = new RenderCommand(); - c->m_shaderDna = dnas[i % 5]; + RenderCommand c; + c.m_shaderDna = dnas[i % 5]; rawCommands.push_back(c); } @@ -192,18 +192,18 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); ProgramDNA targetDNA; for (int j = 0; j < sortedCommands.size(); ++j) { if (j % 4 == 0) { - targetDNA = sortedCommands.at(j)->m_shaderDna; + targetDNA = sortedCommands.at(j).m_shaderDna; if (j > 0) - QVERIFY(targetDNA != sortedCommands.at(j - 1)->m_shaderDna); + QVERIFY(targetDNA != sortedCommands.at(j - 1).m_shaderDna); } - QCOMPARE(targetDNA, sortedCommands.at(j)->m_shaderDna); + QCOMPARE(targetDNA, sortedCommands.at(j).m_shaderDna); } // RenderCommands are deleted by RenderView dtor @@ -247,12 +247,12 @@ private Q_SLOTS: QFETCH(QVector, expectedMinimizedParameters); RenderView renderView; - QVector rawCommands; + QVector rawCommands; for (int i = 0, m = programDNAs.size(); i < m; ++i) { - RenderCommand *c = new RenderCommand(); - c->m_shaderDna = programDNAs.at(i); - c->m_parameterPack = rawParameters.at(i); + RenderCommand c; + c.m_shaderDna = programDNAs.at(i); + c.m_parameterPack = rawParameters.at(i); rawCommands.push_back(c); } @@ -261,13 +261,13 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands, sortedCommands); for (int i = 0, m = programDNAs.size(); i < m; ++i) { - const RenderCommand *c = sortedCommands.at(i); - QCOMPARE(c->m_shaderDna, programDNAs.at(i)); - compareShaderParameterPacks(c->m_parameterPack, expectedMinimizedParameters.at(i)); + const RenderCommand c = sortedCommands.at(i); + QCOMPARE(c.m_shaderDna, programDNAs.at(i)); + compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); } } @@ -276,14 +276,14 @@ private Q_SLOTS: { // GIVEN RenderView renderView; - QVector rawCommands; + QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::FrontToBack); for (int i = 0; i < 200; ++i) { - RenderCommand *c = new RenderCommand(); - c->m_depth = float(i); + RenderCommand c; + c.m_depth = float(i); rawCommands.push_back(c); } @@ -293,10 +293,10 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1)->m_depth < sortedCommands.at(j)->m_depth); + QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth); // RenderCommands are deleted by RenderView dtor } @@ -305,14 +305,14 @@ private Q_SLOTS: { // GIVEN RenderView renderView; - QVector rawCommands; + QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::StateChangeCost); for (int i = 0; i < 200; ++i) { - RenderCommand *c = new RenderCommand(); - c->m_changeCost = i; + RenderCommand c; + c.m_changeCost = i; rawCommands.push_back(c); } @@ -322,10 +322,10 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1)->m_changeCost > sortedCommands.at(j)->m_changeCost); + QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost); // RenderCommands are deleted by RenderView dtor } @@ -334,7 +334,7 @@ private Q_SLOTS: { // GIVEN RenderView renderView; - QVector rawCommands; + QVector rawCommands; QVector sortTypes; sortTypes.push_back(QSortPolicy::StateChangeCost); @@ -360,24 +360,24 @@ private Q_SLOTS: }; auto buildRC = [] (ProgramDNA dna, float depth, int changeCost) { - RenderCommand *c = new RenderCommand(); - c->m_shaderDna = dna; - c->m_depth = depth; - c->m_changeCost = changeCost; + RenderCommand c; + c.m_shaderDna = dna; + c.m_depth = depth; + c.m_changeCost = changeCost; return c; }; - RenderCommand *c5 = buildRC(dna[3], depth[1], stateChangeCost[1]); - RenderCommand *c3 = buildRC(dna[3], depth[0], stateChangeCost[1]); - RenderCommand *c4 = buildRC(dna[2], depth[1], stateChangeCost[1]); - RenderCommand *c8 = buildRC(dna[1], depth[1], stateChangeCost[1]); - RenderCommand *c0 = buildRC(dna[0], depth[2], stateChangeCost[1]); + RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]); + RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]); + RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]); + RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]); + RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]); - RenderCommand *c2 = buildRC(dna[2], depth[2], stateChangeCost[0]); - RenderCommand *c9 = buildRC(dna[2], depth[0], stateChangeCost[0]); - RenderCommand *c1 = buildRC(dna[1], depth[0], stateChangeCost[0]); - RenderCommand *c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); - RenderCommand *c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); + RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]); + RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]); + RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]); + RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); + RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9; @@ -387,12 +387,9 @@ private Q_SLOTS: renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (RenderCommand *rc : sortedCommands) - qDebug() << rc->m_changeCost << rc->m_shaderDna << rc->m_depth; - // Ordered by higher state, higher shaderDNA and higher depth QCOMPARE(c0, sortedCommands.at(4)); QCOMPARE(c3, sortedCommands.at(1)); @@ -423,61 +420,60 @@ private Q_SLOTS: Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId(); Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId(); - RenderCommand *a = new RenderCommand(); + RenderCommand a; { ShaderParameterPack pack; pack.setTexture(0, 0, tex1); pack.setTexture(1, 0, tex3); pack.setTexture(2, 0, tex4); pack.setTexture(3, 0, tex2); - a->m_parameterPack = pack; + a.m_parameterPack = pack; } - RenderCommand *b = new RenderCommand(); - RenderCommand *c = new RenderCommand(); + RenderCommand b; + RenderCommand c; { ShaderParameterPack pack; pack.setTexture(0, 0, tex1); pack.setTexture(3, 0, tex2); - c->m_parameterPack = pack; + c.m_parameterPack = pack; } - RenderCommand *d = new RenderCommand(); + RenderCommand d; { ShaderParameterPack pack; pack.setTexture(1, 0, tex3); pack.setTexture(2, 0, tex4); - d->m_parameterPack = pack; + d.m_parameterPack = pack; } - RenderCommand *e = new RenderCommand(); + RenderCommand e; { ShaderParameterPack pack; pack.setTexture(3, 0, tex2); - e->m_parameterPack = pack; + e.m_parameterPack = pack; } - RenderCommand *f = new RenderCommand(); + RenderCommand f; { ShaderParameterPack pack; pack.setTexture(3, 0, tex2); - f->m_parameterPack = pack; + f.m_parameterPack = pack; } - RenderCommand *g = new RenderCommand(); + RenderCommand g; { ShaderParameterPack pack; pack.setTexture(0, 0, tex1); pack.setTexture(1, 0, tex3); pack.setTexture(2, 0, tex4); pack.setTexture(3, 0, tex2); - g->m_parameterPack = pack; + g.m_parameterPack = pack; } // WHEN - QVector rawCommands = {a, b, c, d, e, f, g}; + QVector rawCommands = {a, b, c, d, e, f, g}; renderView.addSortType(sortTypes); renderView.setCommands(rawCommands); renderView.sort(); // THEN - const QVector sortedCommands = renderView.commands(); - qDebug() << rawCommands << sortedCommands; + const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); QCOMPARE(sortedCommands.at(0), a); QCOMPARE(sortedCommands.at(1), g); -- cgit v1.2.3 From af354bc1df172be2c255e6b540ce62afa218951f Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 16 Oct 2019 07:49:07 +0200 Subject: Convert LoadBufferJob to use direct sync Change-Id: I44334264fba285494624a8a4ee6ff3b85755402c Reviewed-by: Mike Krus --- tests/auto/render/buffer/tst_buffer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 48215bea5..1b53efd33 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -237,10 +237,7 @@ private Q_SLOTS: backendBuffer.executeFunctor(); // THEN - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast(); - QCOMPARE(change->propertyName(), "data"); - QCOMPARE(change->value().toByteArray(), QByteArrayLiteral("454")); + QCOMPARE(arbiter.events.count(), 0); QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1); QCOMPARE(backendBuffer.pendingBufferUpdates().first().offset, -1); -- cgit v1.2.3 From ae88eeee627664b06935004cc0d2868b65905d62 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 16 Oct 2019 09:19:11 +0200 Subject: Convent SendBufferCaptureJob to direct sync Change-Id: I8d5bc69cb75d73e628f08d70b2e40d665c39802b Reviewed-by: Mike Krus --- tests/auto/render/renderer/tst_renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index 65309707c..f8125bce4 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -88,7 +88,7 @@ private Q_SLOTS: 1); // SendRenderCaptureJob // WHEN - renderer.m_sendBufferCaptureJob->addRequest({nullptr, {}}); + renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); jobs = renderer.preRenderingJobs(); // THEN -- cgit v1.2.3 From 1e499f548a24482a0809a34767a04c91a940ffe8 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Tue, 8 Oct 2019 08:01:10 +0100 Subject: Remove old code from animation classes & update tests Change-Id: Ic91a4f168172d6f34d858488e6fc170e8ed875f9 Reviewed-by: Paul Lemire --- .../channelmapping/tst_channelmapping.cpp | 32 +++++++++++++------ tests/auto/core/qskeleton/tst_qskeleton.cpp | 36 ---------------------- tests/auto/render/skeleton/tst_skeleton.cpp | 23 +------------- 3 files changed, 24 insertions(+), 67 deletions(-) (limited to 'tests') diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp index e108e3d26..26a57449d 100644 --- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp +++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include "testpostmanarbiter.h" @@ -181,16 +180,31 @@ private Q_SLOTS: const char *testName = "translation"; QCOMPARE(qstrcmp(testName, backendMapping.propertyName()), 0); + } -// // WHEN -// const auto skeletonId = Qt3DCore::QNodeId::createId(); -// updateChange = QSharedPointer::create(Qt3DCore::QNodeId()); -// updateChange->setPropertyName("skeleton"); -// updateChange->setValue(QVariant::fromValue(skeletonId)); -// backendMapping.sceneChangeEvent(updateChange); + void checkSkeletonPropertyUpdate() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + Qt3DAnimation::Animation::Handler handler; + Qt3DAnimation::Animation::ChannelMapping backendMapping; + backendMapping.setHandler(&handler); + simulateInitializationSync(&mapping, &backendMapping); -// // THEN -// QCOMPARE(backendMapping.skeletonId(), skeletonId); + // WHEN + mapping.setEnabled(false); + backendMapping.syncFromFrontEnd(&mapping, false); + + // THEN + QCOMPARE(backendMapping.isEnabled(), false); + + // WHEN + auto skeleton = new Qt3DCore::QSkeleton; + mapping.setSkeleton(skeleton); + backendMapping.syncFromFrontEnd(&mapping, false); + + // THEN + QCOMPARE(backendMapping.skeletonId(), skeleton->id()); } }; diff --git a/tests/auto/core/qskeleton/tst_qskeleton.cpp b/tests/auto/core/qskeleton/tst_qskeleton.cpp index 299567806..5c88bd754 100644 --- a/tests/auto/core/qskeleton/tst_qskeleton.cpp +++ b/tests/auto/core/qskeleton/tst_qskeleton.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include @@ -160,41 +159,6 @@ private Q_SLOTS: // THEN Should not crash when the joint is destroyed (tests for failed removal of destruction helper) } } - - void checkJointCountPropertyUpdate() - { - // GIVEN - TestArbiter arbiter; - arbiter.setArbiterOnNode(this); - QSignalSpy spy(this, SIGNAL(jointCountChanged(int))); - const int newJointCount = 99; - - // THEN - QVERIFY(spy.isValid()); - - // WHEN - auto valueChange = QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); - valueChange->setPropertyName("jointCount"); - valueChange->setValue(QVariant(newJointCount)); - sceneChangeEvent(valueChange); - - // THEN - QCOMPARE(spy.count(), 1); - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(jointCount(), newJointCount); - - // WHEN - spy.clear(); - sceneChangeEvent(valueChange); - - // THEN - QCOMPARE(spy.count(), 0); - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(jointCount(), newJointCount); - - // Cleanup - QNodePrivate::get(this)->setArbiter(nullptr); - } }; QTEST_MAIN(tst_QSkeleton) diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp index 6af055fb0..2786f27a8 100644 --- a/tests/auto/render/skeleton/tst_skeleton.cpp +++ b/tests/auto/render/skeleton/tst_skeleton.cpp @@ -34,9 +34,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -49,24 +47,6 @@ Q_DECLARE_METATYPE(Qt3DRender::Render::JointInfo) Q_DECLARE_METATYPE(Qt3DRender::Render::SkeletonData) Q_DECLARE_METATYPE(Qt3DCore::Sqt) -namespace { - -void linearizeTreeHelper(QJoint *joint, QVector &joints) -{ - joints.push_back(joint); - for (const auto child : joint->childJoints()) - linearizeTreeHelper(child, joints); -} - -QVector linearizeTree(QJoint *rootJoint) -{ - QVector joints; - linearizeTreeHelper(rootJoint, joints); - return joints; -} - -} - class tst_Skeleton : public Qt3DCore::QBackendNodeTester { Q_OBJECT @@ -155,7 +135,6 @@ private Q_SLOTS: backendSkeleton.setRenderer(&renderer); backendSkeleton.setSkeletonManager(nodeManagers.skeletonManager()); backendSkeleton.setDataType(Skeleton::File); - Qt3DCore::QPropertyUpdatedChangePtr updateChange; // Initialize to ensure skeleton manager is set QSkeletonLoader skeleton; @@ -225,7 +204,7 @@ private Q_SLOTS: QTest::addColumn("skeletonData"); QTest::addColumn("expectedRootJoint"); - QTest::newRow("empty") << SkeletonData() << (QJoint*)nullptr; + QTest::newRow("empty") << SkeletonData() << static_cast(nullptr); SkeletonData skeletonData; JointInfo rootJointInfo; -- cgit v1.2.3 From 7f3bba6e8a4a3bdb36f40a636b76c02902c09d02 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Tue, 22 Oct 2019 07:53:00 +0200 Subject: QMouseEvent: fix BIC issue following Modifier/Modifiers change Will have to be done only in Qt6 unfortunately. For now we abused the fact that an int is used to store the enum so that we store multiple Modifiers values into one Modifiers enum. Change-Id: Ib111140afbe07cfd62fcf3cb8e1a57d3ad848a89 Reviewed-by: Mike Krus --- tests/auto/input/input.pro | 3 +- tests/auto/input/qmouseevent/qmouseevent.pro | 11 +++ tests/auto/input/qmouseevent/tst_qmouseevent.cpp | 93 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 tests/auto/input/qmouseevent/qmouseevent.pro create mode 100644 tests/auto/input/qmouseevent/tst_qmouseevent.cpp (limited to 'tests') diff --git a/tests/auto/input/input.pro b/tests/auto/input/input.pro index 6169d3f7c..7799c2b89 100644 --- a/tests/auto/input/input.pro +++ b/tests/auto/input/input.pro @@ -29,5 +29,6 @@ qtConfig(private_tests) { mousedevice \ utils \ axisaccumulator \ - axisaccumulatorjob + axisaccumulatorjob \ + qmouseevent } diff --git a/tests/auto/input/qmouseevent/qmouseevent.pro b/tests/auto/input/qmouseevent/qmouseevent.pro new file mode 100644 index 000000000..70f4c6eda --- /dev/null +++ b/tests/auto/input/qmouseevent/qmouseevent.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +TARGET = tst_qmouseevent + +QT += 3dcore 3dcore-private 3dinput 3dinput-private testlib + +CONFIG += testcase + +SOURCES += tst_qmouseevent.cpp + +include(../commons/commons.pri) diff --git a/tests/auto/input/qmouseevent/tst_qmouseevent.cpp b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp new file mode 100644 index 000000000..b48afb99d --- /dev/null +++ b/tests/auto/input/qmouseevent/tst_qmouseevent.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include + +class tst_QMouseEvent : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void checkModifiers() + { + { + // GIVEN + QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress, + QPointF(500, 500), + QPointF(500, 500), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + + // WHEN + Qt3DInput::QMouseEvent event3D(event); + + // THEN + QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::NoModifier); + } + { + // GIVEN + QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress, + QPointF(500, 500), + QPointF(500, 500), + Qt::LeftButton, + Qt::LeftButton, + Qt::ShiftModifier); + + // WHEN + Qt3DInput::QMouseEvent event3D(event); + + // THEN + QCOMPARE(event3D.modifiers(), Qt3DInput::QMouseEvent::ShiftModifier); + } + { + // GIVEN + QT_PREPEND_NAMESPACE(QMouseEvent) event(QEvent::MouseButtonPress, + QPointF(500, 500), + QPointF(500, 500), + Qt::LeftButton, + Qt::LeftButton, + Qt::ShiftModifier|Qt::ControlModifier); + + // WHEN + Qt3DInput::QMouseEvent event3D(event); + + // THEN + QCOMPARE(int(event3D.modifiers()), int(Qt3DInput::QMouseEvent::ShiftModifier|Qt3DInput::QMouseEvent::ControlModifier)); + } + } +}; + +QTEST_MAIN(tst_QMouseEvent) + +#include "tst_qmouseevent.moc" -- cgit v1.2.3 From 4d0f8bcdea22f70dbf693545d56e1399b3ca0250 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Tue, 22 Oct 2019 08:03:42 +0100 Subject: Remove remaining messaging code in QSkeletonLoader And matching unit tests Change-Id: Iff0b13b2ad9ff07d08c767f4b20de2a1685a5570 Reviewed-by: Paul Lemire --- .../core/qskeletonloader/tst_qskeletonloader.cpp | 65 ---------------------- tests/auto/render/skeleton/tst_skeleton.cpp | 64 --------------------- 2 files changed, 129 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp index 7fcdc4bbe..f0f4c3872 100644 --- a/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp +++ b/tests/auto/core/qskeletonloader/tst_qskeletonloader.cpp @@ -209,71 +209,6 @@ private Q_SLOTS: QCOMPARE(arbiter.events.size(), 0); } } - - void checkStatusPropertyUpdate() - { - // GIVEN - qRegisterMetaType("Status"); - TestArbiter arbiter; - arbiter.setArbiterOnNode(this); - QSignalSpy spy(this, SIGNAL(statusChanged(Status))); - const QSkeletonLoader::Status newStatus = QSkeletonLoader::Error; - - // THEN - QVERIFY(spy.isValid()); - - // WHEN - QPropertyUpdatedChangePtr valueChange(new QPropertyUpdatedChange(QNodeId())); - valueChange->setPropertyName("status"); - valueChange->setValue(QVariant::fromValue(newStatus)); - sceneChangeEvent(valueChange); - - // THEN - QCOMPARE(spy.count(), 1); - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(status(), newStatus); - - // WHEN - spy.clear(); - sceneChangeEvent(valueChange); - - // THEN - QCOMPARE(spy.count(), 0); - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(status(), newStatus); - - // Cleanup - QNodePrivate::get(this)->setArbiter(nullptr); - } - - void checkRootJointPropertyUpdate() - { - // GIVEN - qRegisterMetaType(); - TestArbiter arbiter; - arbiter.setArbiterOnNode(this); - QSignalSpy spy(this, SIGNAL(rootJointChanged(Qt3DCore::QJoint*))); - std::unique_ptr root(new QJoint()); - - // THEN - QVERIFY(spy.isValid()); - QVERIFY(rootJoint() == nullptr); - - // WHEN - auto valueChange = QJointChangePtr::create(id()); - valueChange->setDeliveryFlags(Qt3DCore::QSceneChange::Nodes); - valueChange->setPropertyName("rootJoint"); - valueChange->data = std::move(root); - sceneChangeEvent(valueChange); - - // THEN - QCOMPARE(spy.count(), 1); - QCOMPARE(arbiter.dirtyNodes.size(), 1); - QVERIFY(rootJoint() != nullptr); - - // Cleanup - QNodePrivate::get(this)->setArbiter(nullptr); - } }; QTEST_MAIN(tst_QSkeletonLoader) diff --git a/tests/auto/render/skeleton/tst_skeleton.cpp b/tests/auto/render/skeleton/tst_skeleton.cpp index 2786f27a8..63ed51058 100644 --- a/tests/auto/render/skeleton/tst_skeleton.cpp +++ b/tests/auto/render/skeleton/tst_skeleton.cpp @@ -198,70 +198,6 @@ private Q_SLOTS: joint->setName(name); QTest::newRow("inverseBind") << m << localPose << name << joint; } - - void checkCreateFrontendJoints_data() - { - QTest::addColumn("skeletonData"); - QTest::addColumn("expectedRootJoint"); - - QTest::newRow("empty") << SkeletonData() << static_cast(nullptr); - - SkeletonData skeletonData; - JointInfo rootJointInfo; - skeletonData.joints.push_back(rootJointInfo); - skeletonData.jointNames.push_back(QLatin1String("rootJoint")); - skeletonData.localPoses.push_back(Qt3DCore::Sqt()); - const int childCount = 10; - for (int i = 0; i < childCount; ++i) { - JointInfo childJointInfo; - childJointInfo.parentIndex = 0; - skeletonData.joints.push_back(childJointInfo); - - const float x = static_cast(i); - Qt3DCore::Sqt localPose; - localPose.translation = QVector3D(x, x, x); - skeletonData.localPoses.push_back(localPose); - - skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); - } - - QJoint *rootJoint = new QJoint(); - for (int i = 0; i < childCount; ++i) { - QJoint *childJoint = new QJoint(); - const float x = static_cast(i); - childJoint->setTranslation(QVector3D(x, x, x)); - rootJoint->addChildJoint(childJoint); - } - - QTest::newRow("wide") << skeletonData << rootJoint; - - skeletonData.joints.clear(); - skeletonData.joints.push_back(rootJointInfo); - for (int i = 0; i < childCount; ++i) { - JointInfo childJointInfo; - childJointInfo.parentIndex = i; - skeletonData.joints.push_back(childJointInfo); - - const float x = static_cast(i); - Qt3DCore::Sqt localPose; - localPose.translation = QVector3D(x, x, x); - skeletonData.localPoses.push_back(localPose); - - skeletonData.jointNames.push_back(QString("Child-%1").arg(i)); - } - - rootJoint = new QJoint(); - QJoint *previousJoint = rootJoint; - for (int i = 0; i < childCount; ++i) { - QJoint *childJoint = new QJoint(); - const float x = static_cast(i); - childJoint->setTranslation(QVector3D(x, x, x)); - previousJoint->addChildJoint(childJoint); - previousJoint = childJoint; - } - - QTest::newRow("deep") << skeletonData << rootJoint; - } }; QTEST_APPLESS_MAIN(tst_Skeleton) -- cgit v1.2.3 From 6303910dc48a87b84112f31c1dd328b930f7e957 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 11 Oct 2019 11:05:12 +0200 Subject: ComputeCommand/SubtreeEnabler use direct sync job to update frontend Change-Id: I773955df33f0b4dcdaa0953633761ff82f3d0da4 Reviewed-by: Mike Krus --- .../render/computecommand/tst_computecommand.cpp | 27 ++++++++++++++-------- tests/auto/render/renderer/tst_renderer.cpp | 8 +++++++ 2 files changed, 26 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp index 990c0cd98..4120153e7 100644 --- a/tests/auto/render/computecommand/tst_computecommand.cpp +++ b/tests/auto/render/computecommand/tst_computecommand.cpp @@ -54,6 +54,7 @@ private Q_SLOTS: QCOMPARE(backendComputeCommand.x(), 1); QCOMPARE(backendComputeCommand.y(), 1); QCOMPARE(backendComputeCommand.z(), 1); + QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false); QCOMPARE(backendComputeCommand.runType(), Qt3DRender::QComputeCommand::Continuous); QCOMPARE(backendComputeCommand.frameCount(), 0); } @@ -61,15 +62,27 @@ private Q_SLOTS: void checkCleanupState() { // GIVEN + TestRenderer renderer; Qt3DRender::Render::ComputeCommand backendComputeCommand; + Qt3DRender::QComputeCommand computeCommand; + computeCommand.setWorkGroupX(256); + computeCommand.setWorkGroupY(512); + computeCommand.setWorkGroupZ(128); + computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual); + computeCommand.trigger(1); // WHEN + backendComputeCommand.setRenderer(&renderer); + simulateInitializationSync(&computeCommand, &backendComputeCommand); + backendComputeCommand.setEnabled(true); + backendComputeCommand.hasReachedFrameCount(); backendComputeCommand.cleanup(); // THEN QCOMPARE(backendComputeCommand.isEnabled(), false); + QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false); } void checkInitializeFromPeer() @@ -207,6 +220,7 @@ private Q_SLOTS: // THEN QCOMPARE(backendComputeCommand.frameCount(), 6 - (i + 1)); QCOMPARE(backendComputeCommand.isEnabled(), true); + QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false); QCOMPARE(arbiter.events.size(), 0); } @@ -214,15 +228,10 @@ private Q_SLOTS: backendComputeCommand.updateFrameCount(); // THEN - QCOMPARE(backendComputeCommand.frameCount(), false); - QCOMPARE(backendComputeCommand.isEnabled(), false); - QCOMPARE(arbiter.events.size(), 1); - { - auto change = arbiter.events.first().staticCast(); - QCOMPARE(change->propertyName(), "enabled"); - QCOMPARE(change->value().value(), false); - QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); - } + QCOMPARE(backendComputeCommand.hasReachedFrameCount(), true); + QCOMPARE(backendComputeCommand.frameCount(), 0); + // Backend stays with enabled == true, frontend will be updated + // to be disabled and backend should be disabled on the next sync } }; diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index f8125bce4..91cb7906c 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -192,6 +192,7 @@ private Q_SLOTS: 1 + // SyncLoadingJobs 1 + // updateLevelOfDetailJob 1 + // cleanupJob + 1 + // sendDisablesToFrontend 1 + // VAOGatherer 1 + // BufferGathererJob 1 + // TexturesGathererJob @@ -221,6 +222,7 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs + 1 + // sendDisablesToFrontend singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + @@ -240,6 +242,7 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs + 1 + // sendDisablesToFrontend 1 + // EntityEnabledDirty singleRenderViewJobCount + layerCacheJobCount); @@ -261,6 +264,7 @@ private Q_SLOTS: 1 + // UpdateShaderDataTransform 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs + 1 + // sendDisablesToFrontend 1 + // ExpandBoundingVolumeJob singleRenderViewJobCount); @@ -278,6 +282,7 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs + 1 + // sendDisablesToFrontend singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount); @@ -301,6 +306,7 @@ private Q_SLOTS: 1 + // ExpandBoundingVolumeJob 1 + // RenderableEntityFilterPtr 1 + // SyncRenderableEntities + 1 + // sendDisablesToFrontend singleRenderViewCommandRebuildJobCount + singleRenderViewJobCount); @@ -321,6 +327,7 @@ private Q_SLOTS: 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob 1 + // BufferGathererJob + 1 + // sendDisablesToFrontend singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -338,6 +345,7 @@ private Q_SLOTS: 1 + // TexturesGathererJob 1 + // updateSkinningPaletteJob 1 + // SyncTexturesGathererJob + 1 + // sendDisablesToFrontend singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); -- cgit v1.2.3 From 257c9bc8b53fb62fcad6bb8977b048d3a7563469 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 16 Oct 2019 10:52:17 +0200 Subject: Renderer: build cache data for new RenderViews Change-Id: I95690444badaf573b9e2775b50c61113de8d1c77 Reviewed-by: Michael Brasser --- tests/auto/render/renderer/tst_renderer.cpp | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index 91cb7906c..0940348bd 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -211,8 +211,35 @@ private Q_SLOTS: renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); renderQueue->reset(); - // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) + // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache) + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // sendDisablesToFrontend + 1 + // LightGathererJob + 1 + // CacheLightJob + 1 + // RenderableEntityFilterJob + 1 + // CacheRenderableEntitiesJob + 1 + // ComputableEntityFilterJob + 1 + // CacheComputableEntitiesJob + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + renderViewBuilderMaterialCacheJobCount + + layerCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache) renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); + renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {}; jobs = renderer.renderBinJobs(); // THEN (level -- cgit v1.2.3 From 84766ed9098f10efc53e4e43a75eef38fce7fbf6 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 21 Oct 2019 17:01:18 +0100 Subject: Fix post FF API changes Change-Id: I347f6df41c0a4f2295831e78248669b4a2d6b5ef Reviewed-by: Paul Lemire --- tests/auto/core/common/testpostmanarbiter.h | 1 + tests/auto/core/nodes/tst_nodes.cpp | 12 +++++++----- tests/auto/render/raycastingjob/tst_raycastingjob.cpp | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/common/testpostmanarbiter.h b/tests/auto/core/common/testpostmanarbiter.h index cecc24f93..6649c7bbe 100644 --- a/tests/auto/core/common/testpostmanarbiter.h +++ b/tests/auto/core/common/testpostmanarbiter.h @@ -28,6 +28,7 @@ #include #include +#include QT_BEGIN_NAMESPACE diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 3b93e7715..25565d470 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -516,7 +517,7 @@ public: void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override { - Q_UNUSED(backend); + Q_UNUSED(backend) auto q = q_func(); if (firstTime) q->allNodes.insert(node->id(), node); @@ -527,10 +528,11 @@ public: TestAspect::TestAspect(QObject *parent) : TestAspect(*new TestAspectPrivate, parent) { - registerBackendType(QSharedPointer::create(this)); - registerBackendType(QSharedPointer::create(this)); - registerBackendType(QSharedPointer::create(this)); - registerBackendType(QSharedPointer::create(this)); + Q_D(TestAspect); + d->registerBackendType(QSharedPointer::create(this)); + d->registerBackendType(QSharedPointer::create(this)); + d->registerBackendType(QSharedPointer::create(this)); + d->registerBackendType(QSharedPointer::create(this)); } TestAspect::TestAspect(TestAspectPrivate &dd, QObject *parent) diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp index 1ff899936..eaf85f5b6 100644 --- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp +++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp @@ -285,7 +285,7 @@ private Q_SLOTS: initializeJob(&rayCastingJob, test.data()); bool earlyReturn = !rayCastingJob.runHelper(); - rayCastingJob.postFrame(test->aspectManager()); + Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager()); QCoreApplication::processEvents(); // THEN @@ -345,7 +345,7 @@ private Q_SLOTS: initializeJob(&rayCastingJob, test.data()); bool earlyReturn = !rayCastingJob.runHelper(); - rayCastingJob.postFrame(test->aspectManager()); + Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager()); QCoreApplication::processEvents(); // THEN -- cgit v1.2.3 From ed97ebb1884b36f7e71b295ebae99fd962832bd3 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Tue, 15 Oct 2019 09:05:05 +0200 Subject: Add manual test to check manual trigger mode on ComputeCommands Change-Id: I8048795277828ecba7d46dbc846685e606b2b8b9 Reviewed-by: Mike Krus --- tests/manual/compute-manual/ComputeFrameGraph.qml | 91 ++++++++++ tests/manual/compute-manual/ComputeMaterial.qml | 118 +++++++++++++ tests/manual/compute-manual/ParticlesScene.qml | 200 ++++++++++++++++++++++ tests/manual/compute-manual/compute-manual.pro | 14 ++ tests/manual/compute-manual/compute-manual.qrc | 11 ++ tests/manual/compute-manual/main.cpp | 66 +++++++ tests/manual/compute-manual/main.qml | 109 ++++++++++++ tests/manual/compute-manual/particles.comp | 31 ++++ tests/manual/compute-manual/particles.frag | 33 ++++ tests/manual/compute-manual/particles.vert | 27 +++ tests/manual/manual.pro | 2 + 11 files changed, 702 insertions(+) create mode 100644 tests/manual/compute-manual/ComputeFrameGraph.qml create mode 100644 tests/manual/compute-manual/ComputeMaterial.qml create mode 100644 tests/manual/compute-manual/ParticlesScene.qml create mode 100644 tests/manual/compute-manual/compute-manual.pro create mode 100644 tests/manual/compute-manual/compute-manual.qrc create mode 100644 tests/manual/compute-manual/main.cpp create mode 100644 tests/manual/compute-manual/main.qml create mode 100644 tests/manual/compute-manual/particles.comp create mode 100644 tests/manual/compute-manual/particles.frag create mode 100644 tests/manual/compute-manual/particles.vert (limited to 'tests') diff --git a/tests/manual/compute-manual/ComputeFrameGraph.qml b/tests/manual/compute-manual/ComputeFrameGraph.qml new file mode 100644 index 000000000..47d57161c --- /dev/null +++ b/tests/manual/compute-manual/ComputeFrameGraph.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 Qt3D.Core 2.14 +import Qt3D.Render 2.14 + +Viewport { + property alias camera: selector.camera + + RenderSurfaceSelector { + id: surfaceSelector + + // Clear Buffer + ClearBuffers { + buffers: ClearBuffers.ColorDepthBuffer + NoDraw {} + } + + // Compute Pass + DispatchCompute { + // 1024 x 1024 particles + // We will launch 1024 local workgroup that will work + // on 1024 particles each + workGroupX: 1024; workGroupY: 1; workGroupZ: 1 + TechniqueFilter { + matchAll: [ + FilterKey { name: "type"; value: "compute"} + ] + } + } + + // Draw particles from buffer computed in the Compute Pass + CameraSelector { + id: selector + TechniqueFilter { + MemoryBarrier { waitFor: MemoryBarrier.VertexAttributeArray } + matchAll: [ + FilterKey { name: "type"; value: "draw"} + ] + } + } + } +} + diff --git a/tests/manual/compute-manual/ComputeMaterial.qml b/tests/manual/compute-manual/ComputeMaterial.qml new file mode 100644 index 000000000..9116a8b66 --- /dev/null +++ b/tests/manual/compute-manual/ComputeMaterial.qml @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 Qt3D.Core 2.14 +import Qt3D.Render 2.14 + +Material { + property Buffer dataBuffer; + property real particleStep: 0.4 + property real finalCollisionFactor: 0.2 + + parameters: [ + Parameter { name: "particleStep"; value: particleStep }, + Parameter { name: "finalCollisionFactor"; value: finalCollisionFactor } + ] + + ShaderProgram { + id: computeShader + computeShaderCode: loadSource("qrc:/particles.comp") + } + + ShaderProgram { + id: drawShader + vertexShaderCode: loadSource("qrc:/particles.vert") + fragmentShaderCode: loadSource("qrc:/particles.frag") + } + + effect: Effect { + techniques: [ + Technique { + renderPasses: [ + RenderPass { + shaderProgram: computeShader + // We set the buffer as the parameter data + parameters: [ + Parameter { name: "Particles"; value: dataBuffer } + ] + } + ] + filterKeys: [ + FilterKey { name: "type"; value: "compute" } + ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 4 + minorVersion: 3 + } + }, + Technique { + renderPasses: [ + RenderPass { + shaderProgram: drawShader + // We assume the mesh to be drawn will also receive + // Vertex buffers attributes that will be used to position and color + } + ] + filterKeys: [ + FilterKey { name: "type"; value: "draw" } + ] + graphicsApiFilter { + api: GraphicsApiFilter.OpenGL + profile: GraphicsApiFilter.CoreProfile + majorVersion: 4 + minorVersion: 3 + } + } + ] // techniques + } +} + diff --git a/tests/manual/compute-manual/ParticlesScene.qml b/tests/manual/compute-manual/ParticlesScene.qml new file mode 100644 index 000000000..68572f6b4 --- /dev/null +++ b/tests/manual/compute-manual/ParticlesScene.qml @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 Qt3D.Core 2.14 +import Qt3D.Render 2.14 +import Qt3D.Extras 2.14 +import Qt3D.Input 2.14 + +Entity { + + property alias computeMode: particlesComputeJob.runType + + function triggerCompute(frames) { + particlesComputeJob.trigger(frames) + } + + components: [ + RenderSettings { + ComputeFrameGraph { + camera: sceneCamera + } + // explicitly set RenderingPolicy to AlwaysRender, as changes in the + // scene won't be reflected in actual Qt scene-graph changes (due to + // GPU compute calls) + renderPolicy: RenderSettings.Always + }, + InputSettings {} + ] + + FirstPersonCameraController { camera: sceneCamera } + + Camera { + id: sceneCamera + projectionType: CameraLens.PerspectiveProjection + viewCenter: Qt.vector3d(0, 0, 0) + position: Qt.vector3d(0, 20, -800) + nearPlane: 0.1 + farPlane: 1000 + fieldOfView: 60 + } + + property int particlesCount: 1024 * 1024 + readonly property int floatSize: 4 + + function buildParticlesBuffer() { + var byteSizeOfParticleData = 8; + var bufferData = new Float32Array(particlesCount * byteSizeOfParticleData); + for (var x = 0; x < 1024; ++x) { + for (var z = 0; z < 1024; ++z) { + var i = x * 1024 + z; + var positionIdx = i * byteSizeOfParticleData; + var colorIdx = i * byteSizeOfParticleData + 8; + + bufferData[positionIdx] = -1024 + x * 2; + bufferData[positionIdx + 1] = 0; + bufferData[positionIdx + 2] = -1024 + z * 2; + bufferData[positionIdx + 3] = 1.0; + + bufferData[colorIdx] = 0.25 + Math.sin(x / 1024) * 0.75; + bufferData[colorIdx + 1] = 0.25 + Math.sin(z / 1024) * 0.75; + bufferData[colorIdx + 2] = 0.25 + Math.sin(x / 1024) * 0.75; + bufferData[colorIdx + 3] = 1.0; + } + } + return bufferData + } + + Buffer { + id: particleBuffer + type: Buffer.VertexBuffer + // struct ParticleData + // { + // vec3 position; // Aligned to 4 floats + // vec3 color; // Aligned to 4 floats + // }; + data: buildParticlesBuffer() + } + + Attribute { + id: particlePositionDataAttribute + name: "particlePosition" + attributeType: Attribute.VertexAttribute + vertexBaseType: Attribute.Float + vertexSize: 3 + divisor: 1 + byteStride: 8 * floatSize + buffer: particleBuffer + } + + Attribute { + id: particleColorDataAttribute + name: "particleColor" + attributeType: Attribute.VertexAttribute + vertexBaseType: Attribute.Float + vertexSize: 3 + divisor: 1 + byteOffset: 4 * floatSize + byteStride: 8 * floatSize + buffer: particleBuffer + } + + ComputeMaterial { + id: computeMaterial + dataBuffer: particleBuffer + } + + ComputeCommand { + id: particlesComputeJob + onRunTypeChanged: { + // Don't forget to re-enable the command + // when switching back to continuous + if (runType === ComputeCommand.Continuous) + enabled = true + } + } + + Entity { + id: particleComputeEntity + components: [ + particlesComputeJob, + computeMaterial + ] + } + + SphereGeometry { + id: sphereGeometry + rings: 10 + slices: 10 + radius: 1 + // Additional Attributes + attributes: [ + particlePositionDataAttribute, + particleColorDataAttribute + ] + } + + Entity { + id: particleRenderEntity + readonly property GeometryRenderer particlesRenderer: GeometryRenderer { + instanceCount: particlesCount + indexOffset: 0 + firstInstance: 0 + primitiveType: GeometryRenderer.Triangles + geometry: sphereGeometry + } + + components: [ + particlesRenderer, + computeMaterial + ] + } +} + diff --git a/tests/manual/compute-manual/compute-manual.pro b/tests/manual/compute-manual/compute-manual.pro new file mode 100644 index 000000000..e2a9116db --- /dev/null +++ b/tests/manual/compute-manual/compute-manual.pro @@ -0,0 +1,14 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dquick 3dinput quick qml + +HEADERS += \ + + +RESOURCES += \ + compute-manual.qrc + +SOURCES += \ + main.cpp diff --git a/tests/manual/compute-manual/compute-manual.qrc b/tests/manual/compute-manual/compute-manual.qrc new file mode 100644 index 000000000..0f94fddd5 --- /dev/null +++ b/tests/manual/compute-manual/compute-manual.qrc @@ -0,0 +1,11 @@ + + + main.qml + ComputeFrameGraph.qml + ComputeMaterial.qml + particles.frag + particles.vert + ParticlesScene.qml + particles.comp + + diff --git a/tests/manual/compute-manual/main.cpp b/tests/manual/compute-manual/main.cpp new file mode 100644 index 000000000..afc9df36a --- /dev/null +++ b/tests/manual/compute-manual/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char* argv[]) +{ + QGuiApplication app(argc, argv); + + QQuickView view; + + view.resize(1024, 1024); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/compute-manual/main.qml b/tests/manual/compute-manual/main.qml new file mode 100644 index 000000000..a76c8ae0c --- /dev/null +++ b/tests/manual/compute-manual/main.qml @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 QtQuick 2.14 +import QtQuick.Scene3D 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.1 +import Qt3D.Render 2.14 + +Item { + + Scene3D { + anchors.fill: parent + aspects: ["input", "logic"] + focus: true + ParticlesScene { + id: scene + computeMode: runModeCombo.currentIndex === 0 ? ComputeCommand.Continuous : ComputeCommand.Manual + } + } + + RowLayout { + id: colorLayout + anchors.left: parent.left + anchors.leftMargin: 35 + anchors.bottom: parent.bottom + anchors.bottomMargin: 35 + spacing: 15 + + RowLayout { + Text { + text: "Run Mode:" + color: "white" + } + ComboBox { + id: runModeCombo + model: ["Continuous", "Manual"] + } + } + RowLayout { + visible: runModeCombo.currentIndex === 1 + Text { + color: "white" + text: "Frames" + } + SpinBox { + id: frameCountSpinBox + value: 5 + from: 1 + to: 10 + stepSize: 1 + } + Button { + text: "Trigger" + onClicked: { + // Trigger Compute Manual + scene.triggerCompute(frameCountSpinBox.value) + } + } + } + } +} diff --git a/tests/manual/compute-manual/particles.comp b/tests/manual/compute-manual/particles.comp new file mode 100644 index 000000000..b05e49c1d --- /dev/null +++ b/tests/manual/compute-manual/particles.comp @@ -0,0 +1,31 @@ +#version 430 core + +uniform float time; + +layout (local_size_x = 1024) in; + +struct ParticleData +{ + vec4 position; + vec4 color; +}; + +// Particles from previouse frame +layout (std430, binding = 0) coherent buffer Particles +{ + ParticleData particles[]; +} data; + +void main(void) +{ + uint globalId = gl_GlobalInvocationID.x; + + // Retrieve current particle from previous frame + ParticleData currentParticle = data.particles[globalId]; + + // New position = old position + sin(time) + currentParticle.position = currentParticle.position + vec4(0.0, 1.0, 0.0, 0.0) * sin(time * globalId); + + // Save updated particle + data.particles[globalId] = currentParticle; +} diff --git a/tests/manual/compute-manual/particles.frag b/tests/manual/compute-manual/particles.frag new file mode 100644 index 000000000..3f11b9868 --- /dev/null +++ b/tests/manual/compute-manual/particles.frag @@ -0,0 +1,33 @@ +#version 430 core + +out vec4 color; + +in VertexBlock +{ + flat vec3 color; + vec3 pos; + vec3 normal; +} frag_in; + +const vec4 lightPosition = vec4(0.0, 0.0, 0.0, 0.0); +const vec3 lightIntensity = vec3(1.0, 1.0, 1.0); +const vec3 ka = vec3(0.1, 0.1, 0.1); +const vec3 ks = vec3(0.8, 0.8, 0.8); +const float shininess = 50.0; + +vec3 ads() +{ + vec3 n = normalize( frag_in.normal); + vec3 s = normalize( vec3(lightPosition) - frag_in.pos ); + vec3 v = normalize( -frag_in.pos ); + vec3 h = normalize( v + s ); + return lightIntensity * (ka + + frag_in.color * max( dot(s, frag_in.normal ), 0.0 ) + + ks * pow( max( dot( h, n ), 0.0 ), shininess ) ); +} + + +void main(void) +{ + color = vec4(ads(), 1.0); +} diff --git a/tests/manual/compute-manual/particles.vert b/tests/manual/compute-manual/particles.vert new file mode 100644 index 000000000..5f2da2a00 --- /dev/null +++ b/tests/manual/compute-manual/particles.vert @@ -0,0 +1,27 @@ +#version 430 core + +in vec3 vertexPosition; +in vec3 vertexNormal; + +in vec3 particlePosition; +in vec3 particleColor; + +out VertexBlock +{ + flat vec3 color; + vec3 pos; + vec3 normal; +} v_out; + +uniform mat4 mvp; +uniform mat3 modelViewNormal; +uniform mat4 modelView; + +void main(void) +{ + vec4 pos = vec4(vertexPosition.xyz, 1.0) + vec4(particlePosition, 0.0); + gl_Position = mvp * pos; + v_out.pos = vec4(modelView * pos).xyz; + v_out.normal = normalize(modelViewNormal * vertexNormal); + v_out.color = mix(particleColor * 0.2, particleColor, smoothstep(0.5, 0.8, abs(v_out.normal).z)); +} diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 1182886d3..9c2461b29 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -69,6 +69,8 @@ SUBDIRS += \ scene3d-in-sync \ compressed_textures +!macos:!uikit: SUBDIRS += compute-manual + qtHaveModule(multimedia): { SUBDIRS += \ sharedtexture \ -- cgit v1.2.3 From 59bcc05abb8606dfc33086870980ffdf4a3937eb Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 16 Oct 2019 10:52:49 +0200 Subject: Add manual test for QSubtreeEnabler Change-Id: Iff354956c831919cbb9d58f75014be0fa92b45c4 Reviewed-by: Mike Krus Reviewed-by: Michael Brasser --- tests/manual/manual.pro | 4 +- tests/manual/subtree-enabler-qml/FrameGraph.qml | 100 +++++++++++++++++++ tests/manual/subtree-enabler-qml/SimpleCamera.qml | 79 +++++++++++++++ tests/manual/subtree-enabler-qml/main.cpp | 64 ++++++++++++ tests/manual/subtree-enabler-qml/main.qml | 110 +++++++++++++++++++++ .../subtree-enabler-qml/subtree-enabler-qml.pro | 17 ++++ .../subtree-enabler-qml/subtree-enabler-qml.qrc | 7 ++ 7 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tests/manual/subtree-enabler-qml/FrameGraph.qml create mode 100644 tests/manual/subtree-enabler-qml/SimpleCamera.qml create mode 100644 tests/manual/subtree-enabler-qml/main.cpp create mode 100644 tests/manual/subtree-enabler-qml/main.qml create mode 100644 tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro create mode 100644 tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc (limited to 'tests') diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 9c2461b29..3553219e1 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -67,10 +67,12 @@ SUBDIRS += \ qtbug-76766 \ shader-image-qml \ scene3d-in-sync \ - compressed_textures + compressed_textures \ + subtree-enabler-qml !macos:!uikit: SUBDIRS += compute-manual + qtHaveModule(multimedia): { SUBDIRS += \ sharedtexture \ diff --git a/tests/manual/subtree-enabler-qml/FrameGraph.qml b/tests/manual/subtree-enabler-qml/FrameGraph.qml new file mode 100644 index 000000000..b9cdce9ea --- /dev/null +++ b/tests/manual/subtree-enabler-qml/FrameGraph.qml @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 Qt3D.Core 2.14 +import Qt3D.Render 2.14 +import QtQuick 2.14 as QQ2 + +RenderSettings { + id: frameGraph + + property alias leftCamera: cameraSelectorLeftViewport.camera; + property alias rightCamera: cameraSelectorRightViewport.camera; + property alias window: surfaceSelector.surface + + activeFrameGraph: RenderSurfaceSelector { + id: surfaceSelector + + Viewport { + id: mainViewport + normalizedRect: Qt.rect(0, 0, 1, 1) + + ClearBuffers { + buffers: ClearBuffers.ColorDepthBuffer + clearColor: Qt.rgba(0.6, 0.6, 0.6, 1.0) + NoDraw {} + } + + Viewport { + id: leftViewport + normalizedRect: Qt.rect(0, 0, 0.5, 0.5) + CameraSelector { id: cameraSelectorLeftViewport } + } + + SubtreeEnabler { + id: enabler + enabled: true + + QQ2.Timer { + running: true + repeat: true + interval: 1000 + onTriggered: enabler.enabled = !enabler.enabled + } + + Viewport { + id: rightViewport + normalizedRect: Qt.rect(0.5, 0.5, 0.5, 0.5) + CameraSelector { id: cameraSelectorRightViewport } + } + } + } + } +} diff --git a/tests/manual/subtree-enabler-qml/SimpleCamera.qml b/tests/manual/subtree-enabler-qml/SimpleCamera.qml new file mode 100644 index 000000000..a1ef6d01c --- /dev/null +++ b/tests/manual/subtree-enabler-qml/SimpleCamera.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 Qt3D.Core 2.14 +import Qt3D.Render 2.14 + +Entity { + id: root + + property vector3d position: Qt.vector3d(0.0, 0.0, 10.0) + property vector3d viewCenter: Qt.vector3d(0.0, 0.0, 0.0) + property vector3d upVector: Qt.vector3d(0.0, 1.0, 0.0) + property CameraLens lens: null + + components: [lens, transform] + + Transform { + id: transform + matrix: { + var m = Qt.matrix4x4(); + m.translate(root.position) + var zAxis = root.position.minus(root.viewCenter).normalized() + var xAxis = root.upVector.crossProduct(zAxis).normalized(); + var yAxis = zAxis.crossProduct(xAxis); + var r = Qt.matrix4x4(xAxis.x, yAxis.x, zAxis.x, 0, + xAxis.y, yAxis.y, zAxis.y, 0, + xAxis.z, yAxis.z, zAxis.z, 0, + 0, 0, 0, 1) + return m.times(r); + } + } +} diff --git a/tests/manual/subtree-enabler-qml/main.cpp b/tests/manual/subtree-enabler-qml/main.cpp new file mode 100644 index 000000000..ce5b883bd --- /dev/null +++ b/tests/manual/subtree-enabler-qml/main.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#include +#include + +int main(int ac, char **av) +{ + QGuiApplication app(ac, av); + Qt3DExtras::Quick::Qt3DQuickWindow view; + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} + + diff --git a/tests/manual/subtree-enabler-qml/main.qml b/tests/manual/subtree-enabler-qml/main.qml new file mode 100644 index 000000000..c2e530893 --- /dev/null +++ b/tests/manual/subtree-enabler-qml/main.qml @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 QtQuick 2.14 +import Qt3D.Core 2.14 +import Qt3D.Render 2.14 +import Qt3D.Input 2.14 +import Qt3D.Extras 2.14 + +Entity { + id: rootNode + components: [frameGraph] + + FrameGraph { + id: frameGraph + leftCamera: camera1 + rightCamera: camera2 + } + + CameraLens { + id: cameraLens + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + aspectRatio: 16/9 + nearPlane: 0.01 + farPlane: 1000.0 + } + + SimpleCamera { + id: camera1 + lens: cameraLens + position: Qt.vector3d(10.0, 1.0, 10.0) + viewCenter: Qt.vector3d(0.0, 1.0, 0.0) + } + + SimpleCamera { + id: camera2 + lens: cameraLens + position: Qt.vector3d(0.0, 0.0, 5.0) + viewCenter: Qt.vector3d(0.0, 0.0, 0.0) + } + + Entity { + id: sceneRoot + property real rotationAngle: 0 + + SequentialAnimation { + running: true + loops: Animation.Infinite + NumberAnimation { target: sceneRoot; property: "rotationAngle"; to: 360; duration: 4000; } + } + + Entity { + components: [ + Transform { + rotation: fromAxisAndAngle(Qt.vector3d(0, 0, 1), -sceneRoot.rotationAngle) + }, + CylinderMesh {}, + MetalRoughMaterial {} + ] + } + } // sceneRoot +} // rootNode diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro new file mode 100644 index 000000000..ddd0ae561 --- /dev/null +++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.pro @@ -0,0 +1,17 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras + +HEADERS += \ + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml + +RESOURCES += \ + subtree-enabler-qml.qrc \ + diff --git a/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc new file mode 100644 index 000000000..e565b719f --- /dev/null +++ b/tests/manual/subtree-enabler-qml/subtree-enabler-qml.qrc @@ -0,0 +1,7 @@ + + + main.qml + FrameGraph.qml + SimpleCamera.qml + + -- cgit v1.2.3 From 1194641110288b4e58c92cac17c3289ad7cad49d Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Tue, 15 Oct 2019 08:16:35 +0200 Subject: ComputeCommand: add unit tests for manual trigger mode Change-Id: Ia106a235648df7232fbcaf4f61c880a9ab5491ef Reviewed-by: Mike Krus --- .../render/computecommand/tst_computecommand.cpp | 118 +++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'tests') diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp index 4120153e7..2046ecc76 100644 --- a/tests/auto/render/computecommand/tst_computecommand.cpp +++ b/tests/auto/render/computecommand/tst_computecommand.cpp @@ -31,12 +31,37 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #include "qbackendnodetester.h" #include "testrenderer.h" #include "testpostmanarbiter.h" + +// tst_Renderer is a friend class of Renderer +class tst_Renderer : public Qt3DRender::Render::Renderer +{ +public: + tst_Renderer() + : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous) + {} + + ~tst_Renderer() { + shutdown(); + } + + Qt3DRender::Render::SynchronizerPostFramePtr sendDisablesToFrontendJob() const + { + return m_sendDisablesToFrontendJob; + } +}; + + class tst_ComputeCommand : public Qt3DCore::QBackendNodeTester { Q_OBJECT @@ -232,6 +257,99 @@ private Q_SLOTS: QCOMPARE(backendComputeCommand.frameCount(), 0); // Backend stays with enabled == true, frontend will be updated // to be disabled and backend should be disabled on the next sync + + // WHEN + computeCommand.setEnabled(false); + backendComputeCommand.syncFromFrontEnd(&computeCommand, false); + + // THEN + QCOMPARE(backendComputeCommand.isEnabled(), false); + QCOMPARE(backendComputeCommand.frameCount(), 0); + + // WHEN + computeCommand.trigger(1); + backendComputeCommand.syncFromFrontEnd(&computeCommand, false); + + // THEN + QCOMPARE(computeCommand.isEnabled(), true); + QCOMPARE(backendComputeCommand.isEnabled(), true); + QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false); + QCOMPARE(backendComputeCommand.frameCount(), 1); + } + + void checkDisablesFrontend() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManager; + tst_Renderer renderer; + TestArbiter arbiter; + + Qt3DCore::QAspectManager manager; + Qt3DCore::QScene scene; + + Qt3DCore::QEntity rootEntity; + Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene); + + Qt3DRender::QComputeCommand computeCommand; + Qt3DRender::Render::ComputeCommand *backendComputeCommand = nullptr; + + renderer.setNodeManagers(&nodeManager); + + // WHEN + computeCommand.setParent(&rootEntity); + // RootEntity is the entry point to retrieve the scene instance for lookups + manager.setRootEntity(&rootEntity, {}); + + // THEN + QVERIFY(scene.lookupNode(computeCommand.id()) != nullptr); + + // WHEN + auto handle = nodeManager.computeJobManager()->getOrAcquireHandle(computeCommand.id()); + backendComputeCommand = nodeManager.computeJobManager()->data(handle); + + // WHEN + computeCommand.setWorkGroupX(256); + computeCommand.setWorkGroupY(512); + computeCommand.setWorkGroupZ(128); + computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual); + computeCommand.trigger(1); + + Qt3DCore::QBackendNodePrivate::get(backendComputeCommand)->setArbiter(&arbiter); + backendComputeCommand->setRenderer(&renderer); + simulateInitializationSync(&computeCommand, backendComputeCommand); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(),1); + QCOMPARE(backendComputeCommand->isEnabled(), true); + QCOMPARE(computeCommand.isEnabled(), true); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); + + // WHEN + backendComputeCommand->updateFrameCount(); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(), 0); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), true); + + + // Still enabled as we have yet to notify the fronted + QCOMPARE(backendComputeCommand->isEnabled(), true); + QCOMPARE(computeCommand.isEnabled(), true); + + // WHEN + auto sendDisablesJob = renderer.sendDisablesToFrontendJob(); + Qt3DCore::QAspectJobPrivate::get(sendDisablesJob.data())->postFrame(&manager); + + // THEN + QCOMPARE(computeCommand.isEnabled(), false); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); + + // WHEN + backendComputeCommand->syncFromFrontEnd(&computeCommand, false); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(), 0); + QCOMPARE(backendComputeCommand->isEnabled(), false); } }; -- cgit v1.2.3 From ab6a70325e320ff0ea2c5b4673cc9a122ee0f601 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 21 Oct 2019 11:34:10 +0200 Subject: Scene3D: halt Qt3D simulation loop while not visible Change-Id: I09d69fab7aaf3c2fa77da6eb30e505d9cb25c01f Reviewed-by: Mike Krus --- tests/manual/manual.pro | 3 +- tests/manual/scene3d-visibility/main.cpp | 66 +++++++++ tests/manual/scene3d-visibility/main.qml | 161 +++++++++++++++++++++ .../scene3d-visibility/scene3d-visibility.pro | 10 ++ .../scene3d-visibility/scene3d-visibility.qrc | 5 + 5 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 tests/manual/scene3d-visibility/main.cpp create mode 100644 tests/manual/scene3d-visibility/main.qml create mode 100644 tests/manual/scene3d-visibility/scene3d-visibility.pro create mode 100644 tests/manual/scene3d-visibility/scene3d-visibility.qrc (limited to 'tests') diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 3553219e1..dbb1fbc63 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -68,7 +68,8 @@ SUBDIRS += \ shader-image-qml \ scene3d-in-sync \ compressed_textures \ - subtree-enabler-qml + subtree-enabler-qml \ + scene3d-visibility !macos:!uikit: SUBDIRS += compute-manual diff --git a/tests/manual/scene3d-visibility/main.cpp b/tests/manual/scene3d-visibility/main.cpp new file mode 100644 index 000000000..8886263f4 --- /dev/null +++ b/tests/manual/scene3d-visibility/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + QQuickView view; + + view.resize(500, 500); + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:/main.qml")); + view.show(); + + return app.exec(); +} diff --git a/tests/manual/scene3d-visibility/main.qml b/tests/manual/scene3d-visibility/main.qml new file mode 100644 index 000000000..ccfa3227f --- /dev/null +++ b/tests/manual/scene3d-visibility/main.qml @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 QtQuick 2.14 +import Qt3D.Core 2.14 +import Qt3D.Render 2.14 +import Qt3D.Input 2.14 +import Qt3D.Extras 2.14 +import QtQuick.Scene3D 2.14 + +Item { + id: root + + Timer { + running: true + repeat: true + interval: 2000 + onTriggered: scene3d.visible = !scene3d.visible + } + + // Scene3D + Scene3D { + id: scene3d + visible: false + readonly property double halfWidth: width * 0.5 + + focus: true + anchors.fill: parent + // Make sure to define the input aspect if we want to handle inputs + aspects: ["render", "input"] + multisample: false + + Entity { // Root + id: sceneRoot + components: [ + RenderSettings { + activeFrameGraph: ForwardRenderer { + id: forwardRenderer + camera: mainCamera + clearColor: "yellow" + } + }, + // Event Source is the Scene3D in that case + InputSettings { } + ] + + Camera { + id: mainCamera + projectionType: CameraLens.PerspectiveProjection + fieldOfView: 45 + nearPlane : 0.1 + farPlane : 1000.0 + position: Qt.vector3d( 0.0, 0.0, -40.0 ) + upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) + viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) + } + + PhongMaterial { + id: material + } + + TorusMesh { + id: torusMesh + radius: 5 + minorRadius: 1 + rings: 100 + slices: 20 + } + + SphereMesh { + id: sphereMesh + radius: 3 + } + + Transform { + id: torusTransform + scale3D: Qt.vector3d(1.5, 1, 0.5) + rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) + } + + Transform { + id: sphereTransform + property real userAngle: 0.0 + matrix: { + var m = Qt.matrix4x4(); + m.rotate(userAngle, Qt.vector3d(0, 1, 0)); + m.translate(Qt.vector3d(20, 0, 0)); + return m; + } + + onWorldMatrixChanged: console.log("Sphere WorldMatrix " + worldMatrix) + } + + NumberAnimation { + target: sphereTransform + property: "userAngle" + duration: 1000 + from: 0 + to: 360 + loops: Animation.Infinite + running: true + } + + Entity { + id: torusEntity + components: [ torusMesh, material, torusTransform ] + } + Entity { + id: sphereEntity + components: [ sphereMesh, material, sphereTransform ] + } + } + } +} diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.pro b/tests/manual/scene3d-visibility/scene3d-visibility.pro new file mode 100644 index 000000000..a1c20a502 --- /dev/null +++ b/tests/manual/scene3d-visibility/scene3d-visibility.pro @@ -0,0 +1,10 @@ +QT += qml quick 3dinput + +SOURCES += \ + main.cpp + +OTHER_FILES += \ + main.qml + +RESOURCES += \ + scene3d-visibility.qrc diff --git a/tests/manual/scene3d-visibility/scene3d-visibility.qrc b/tests/manual/scene3d-visibility/scene3d-visibility.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/tests/manual/scene3d-visibility/scene3d-visibility.qrc @@ -0,0 +1,5 @@ + + + main.qml + + -- cgit v1.2.3 From 8c4520c93aa7f53a225c3b5f33a272647833b679 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 25 Oct 2019 07:18:47 +0200 Subject: Add manual test to check manual render loop Shows that update are done before rendering takes place Change-Id: Ia3f5bcb497c023dad805609dcb1ffe9ce7947c06 Task-number: QTBUG-79375 Reviewed-by: Mike Krus --- tests/manual/manual-renderloop/main.cpp | 211 +++++++++++++++++++++ .../manual/manual-renderloop/manual-renderloop.pro | 8 + tests/manual/manual.pro | 3 +- 3 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 tests/manual/manual-renderloop/main.cpp create mode 100644 tests/manual/manual-renderloop/manual-renderloop.pro (limited to 'tests') diff --git a/tests/manual/manual-renderloop/main.cpp b/tests/manual/manual-renderloop/main.cpp new file mode 100644 index 000000000..f2a49cb86 --- /dev/null +++ b/tests/manual/manual-renderloop/main.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class ManualRenderer +{ +public: + ManualRenderer() + : m_aspectEngine(new Qt3DCore::QAspectEngine()) + , m_renderAspect(new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous)) + { + } + + ~ManualRenderer() { + m_aspectEngine->setRootEntity(Qt3DCore::QEntityPtr()); + m_aspectEngine->unregisterAspect(m_renderAspect); + delete m_renderAspect; + delete m_aspectEngine; + } + + void initialize(QWindow *window, QOpenGLContext *glCtx) + { + m_aspectEngine->registerAspect(m_renderAspect); + m_aspectEngine->setRunMode(Qt3DCore::QAspectEngine::Manual); + + Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast + (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect)); + dRenderAspect->renderInitialize(glCtx); + + m_rootEntity.reset(createSceneTree(window)); + m_aspectEngine->setRootEntity(m_rootEntity); + } + + void render() { + qDebug() << Q_FUNC_INFO << "Updating Scene"; + updateScene(); + qDebug() << Q_FUNC_INFO << "Processing Frame"; + // Launch jobs to process the frame + m_aspectEngine->processFrame(); + qDebug() << Q_FUNC_INFO << "Rendering Frame"; + // Submit Render Queues + Qt3DRender::QRenderAspectPrivate *dRenderAspect = static_cast + (Qt3DRender::QRenderAspectPrivate::get(m_renderAspect)); + dRenderAspect->renderSynchronous(true); + } + +private: + Qt3DCore::QEntity *createSceneTree(QWindow *surface) { + // Root entity in the 3D scene. + Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity; + auto camera = new Qt3DRender::QCamera(rootEntity); + camera->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f); + camera->setPosition(QVector3D(0, 0, 40.0f)); + camera->setViewCenter(QVector3D(0, 0, 0)); + + // Torus + Qt3DCore::QEntity *torusEntity = new Qt3DCore::QEntity(rootEntity); + auto material = new Qt3DExtras::QPhongMaterial(rootEntity); + auto torusTransform = new Qt3DCore::QTransform; + auto torusMesh = new Qt3DExtras::QTorusMesh; + + torusMesh->setRadius(5); + torusMesh->setMinorRadius(1); + torusMesh->setRings(100); + torusMesh->setSlices(20); + + torusTransform->setScale3D(QVector3D(1.5, 1, 0.5)); + torusTransform->setRotation(QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), 45.0f)); + + torusEntity->addComponent(torusMesh); + torusEntity->addComponent(material); + torusEntity->addComponent(torusTransform); + + // FrameGraph + auto forwardRenderer = new Qt3DExtras::QForwardRenderer(); + forwardRenderer->setSurface(surface); + forwardRenderer->setCamera(camera); + forwardRenderer->setClearColor(QColor(Qt::black)); + + auto renderSettings = new Qt3DRender::QRenderSettings(); + renderSettings->setActiveFrameGraph(forwardRenderer); + rootEntity->addComponent(renderSettings); + + return rootEntity; + } + + void updateScene() + { + static int angle = 0; + // Update camera position + auto camera = m_rootEntity->findChild(); + Q_ASSERT(camera); + + const double angleRad = qDegreesToRadians(double(angle)); + const QVector3D newPos(qSin(angleRad), 0.0, qCos(angleRad)); + camera->setPosition(newPos * 40.0f); + + qDebug() << Q_FUNC_INFO << "Camera Transform Matrix" << camera->transform()->matrix(); + qDebug() << Q_FUNC_INFO << "Camera ViewMatrix" << camera->viewMatrix(); + + angle = (angle + 1) % 360; + } + + Qt3DCore::QEntityPtr m_rootEntity; + Qt3DCore::QAspectEngine *m_aspectEngine; + Qt3DRender::QRenderAspect *m_renderAspect; +}; + +int main(int ac, char **av) +{ + QSurfaceFormat format = QSurfaceFormat::defaultFormat(); +#ifdef QT_OPENGL_ES_2 + format.setRenderableType(QSurfaceFormat::OpenGLES); +#else + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(4, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + } +#endif + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(format); + + QGuiApplication app(ac, av); + + QWindow win; + win.setSurfaceType(QSurface::OpenGLSurface); + win.resize(1024, 768); + win.setFormat(format); + win.show(); + + QOpenGLContext ctx; + ctx.setFormat(format); + const bool ctxCreated = ctx.create(); + + if (!ctxCreated) { + qWarning() << "Failed to create GL context"; + return -1; + } + + ManualRenderer renderer; + renderer.initialize(&win, &ctx); + + QTimer t; + QObject::connect(&t, &QTimer::timeout, [&] { renderer.render(); }); + t.start(16); + + return app.exec(); +} diff --git a/tests/manual/manual-renderloop/manual-renderloop.pro b/tests/manual/manual-renderloop/manual-renderloop.pro new file mode 100644 index 000000000..d126a48c5 --- /dev/null +++ b/tests/manual/manual-renderloop/manual-renderloop.pro @@ -0,0 +1,8 @@ +!include( ../manual.pri ) { + error( "Couldn't find the manual.pri file!" ) +} + +QT += 3dcore 3drender 3drender-private 3dinput 3dextras + +SOURCES += \ + main.cpp diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index dbb1fbc63..2f630e0d9 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -69,7 +69,8 @@ SUBDIRS += \ scene3d-in-sync \ compressed_textures \ subtree-enabler-qml \ - scene3d-visibility + scene3d-visibility \ + manual-renderloop !macos:!uikit: SUBDIRS += compute-manual -- cgit v1.2.3 From fe790f1537d17fca586a2c6ea7f57c02cfab1b88 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 25 Oct 2019 08:41:37 +0200 Subject: QNode::updateNode: ensure postConstructorInit of node is called When a QNode subclass is created doing Subclass(parent) with parent != nullptr QNodePrivate::_q_postContrustorInit is called through a queued invocation due to the fact that the QNode ctor is called before the subclass ctor is (and we need the class to be fully constructed to do proper initialization). When adding a QNode subclass created as described above, and immediately referencing it as a property of another QNode, we can end up in cases where the backend gets aware of the node being referenced in the relationship and tries to create its backend. Unfortunately due to the queued invocation of _q_postConstructorInit, the frontend node has yet to be fully initialized, resulting in the creation of the backend node to assert/crash. Therefore, when updateNode is called (whenever a subnode is referenced in a relationship) we now ensure that postConstructorInit gets (or has already been) called. Change-Id: Iea6e0b5a59c676f5db2946bec2f8c345accc32b0 Task-number: QTBUG-79350 Reviewed-by: Mike Krus --- tests/auto/core/nodes/tst_nodes.cpp | 106 ++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 29 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 25565d470..b5291cab7 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -93,6 +94,7 @@ private slots: void checkConstructionWithNonRootParent(); // QTBUG-73986 void checkConstructionAsListElement(); void checkSceneIsSetOnConstructionWithParent(); // QTBUG-69352 + void checkSubNodePostConstructIsCalledWhenReferincingNodeProperty(); // QTBUG-79350 void appendingComponentToEntity(); void appendingParentlessComponentToEntityWithoutScene(); @@ -291,22 +293,15 @@ public slots: if (!attribute->parent()) attribute->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } + d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueAdded); } } void removeAttribute(MyQNode *attribute) { Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeRemovedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } + d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved); + m_attributes.removeOne(attribute); // Remove bookkeeping connection d->unregisterDestructionHelper(attribute); @@ -385,11 +380,7 @@ public: if (!attribute->parent()) attribute->setParent(this); - if (d->m_changeArbiter != nullptr) { - const auto change = Qt3DCore::QPropertyNodeAddedChangePtr::create(id(), attribute); - change->setPropertyName("attribute"); - d->notifyObservers(change); - } + d->updateNode(attribute, "attribute", Qt3DCore::PropertyValueRemoved); } } @@ -436,6 +427,29 @@ public: } }; +class MyFakeMaterial : public Qt3DCore::QComponent +{ + Q_OBJECT +public: + explicit MyFakeMaterial(Qt3DCore::QNode *parent = nullptr) + : QComponent(parent) + , m_effect(new MyQNode(this)) + , m_technique(new MyQNode(m_effect)) + , m_renderPass(new MyQNode(m_technique)) + { + } + + void setArbiter(Qt3DCore::QAbstractArbiter *arbiter) + { + Q_ASSERT(arbiter); + Qt3DCore::QComponentPrivate::get(this)->setArbiter(arbiter); + } + + MyQNode *m_effect; + MyQNode *m_technique; + MyQNode *m_renderPass; +}; + class TestAspectPrivate; class TestAspect : public Qt3DCore::QAbstractAspect { @@ -1545,20 +1559,8 @@ void tst_Nodes::checkConstructionAsListElement() QCoreApplication::processEvents(); QCOMPARE(root->children().count(), 1); - QCOMPARE(spy.events.size(), 2); // 1 child added change, 1 property change - - const auto newChildEvent = spy.events.takeFirst().change().dynamicCast(); - QVERIFY(!newChildEvent.isNull()); - QCOMPARE(newChildEvent->subjectId(), root->id()); - QCOMPARE(newChildEvent->propertyName(), "children"); - QCOMPARE(newChildEvent->addedNodeId(), node->id()); - - // Ensure second and last event is property set change - const auto propertyEvent = spy.events.takeFirst().change().dynamicCast(); - QVERIFY(!propertyEvent.isNull()); - QCOMPARE(propertyEvent->subjectId(), root->id()); - QCOMPARE(propertyEvent->propertyName(), "attribute"); - QCOMPARE(newChildEvent->addedNodeId(), node->id()); + QCOMPARE(spy.dirtyNodes.size(), 1); // 1 property change + QCOMPARE(spy.dirtySubNodes.size(), 1); // 1 child added change } void tst_Nodes::checkSceneIsSetOnConstructionWithParent() @@ -1607,6 +1609,52 @@ void tst_Nodes::checkSceneIsSetOnConstructionWithParent() QCOMPARE(spy.dirtySubNodes.size(), 5); // 5 entities changed } +void tst_Nodes::checkSubNodePostConstructIsCalledWhenReferincingNodeProperty() +{ + // GIVEN + ObserverSpy spy; + Qt3DCore::QAspectEngine engine; + Qt3DCore::QScene scene(&engine); + QScopedPointer root(new MyQNode()); + + // WHEN + root->setArbiterAndScene(&spy, &scene); + root->setSimulateBackendCreated(true); + + // THEN + QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->scene() != nullptr); + + // WHEN + Qt3DCore::QEntity *subTreeRoot = new Qt3DCore::QEntity(root.data()); + QCoreApplication::processEvents(); + + // THEN + QVERIFY(Qt3DCore::QNodePrivate::get(subTreeRoot)->m_hasBackendNode); + + // WHEN + MyFakeMaterial *material = new MyFakeMaterial(subTreeRoot); + subTreeRoot->addComponent(material); + + // THEN + QVERIFY(Qt3DCore::QNodePrivate::get(material)->m_hasBackendNode); + QVERIFY(Qt3DCore::QNodePrivate::get(material->m_effect)->m_hasBackendNode); + QVERIFY(Qt3DCore::QNodePrivate::get(material->m_technique)->m_hasBackendNode); + QVERIFY(Qt3DCore::QNodePrivate::get(material->m_renderPass)->m_hasBackendNode); + + // WHEN + MyQNode *fakeRenderState = new MyQNode(material); + Qt3DCore::QNodePrivate *dPtr = Qt3DCore::QNodePrivate::get(fakeRenderState); + + // THEN + QVERIFY(!dPtr->m_hasBackendNode); + + // WHEN + material->m_renderPass->addAttribute(fakeRenderState); + + // THEN + QVERIFY(dPtr->m_hasBackendNode); +} + void tst_Nodes::appendingParentlessComponentToEntityWithoutScene() { // GIVEN -- cgit v1.2.3 From 3c5848a923b9b9393753c654e837fc8c99bd8b23 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 16 Oct 2019 15:55:42 +0200 Subject: Compute renderables/computables/lights once instead of once per RV All RV end up using exactly the same vector before filtering it down on per RV specifics. No point in compute RV times the same thing. Change-Id: Ia674095627771c8e9ada090fa47623cbbbd8a3f8 Reviewed-by: Paul Lemire --- tests/auto/render/renderer/tst_renderer.cpp | 6 -- .../renderviewbuilder/tst_renderviewbuilder.cpp | 76 ++++++---------------- 2 files changed, 20 insertions(+), 62 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index 0940348bd..a343d6e57 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -223,12 +223,6 @@ private Q_SLOTS: 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs 1 + // sendDisablesToFrontend - 1 + // LightGathererJob - 1 + // CacheLightJob - 1 + // RenderableEntityFilterJob - 1 + // CacheRenderableEntitiesJob - 1 + // ComputableEntityFilterJob - 1 + // CacheComputableEntitiesJob singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp index 0fb1f5e24..6024084bd 100644 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp @@ -52,6 +52,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -280,39 +281,6 @@ private Q_SLOTS: // mark jobs dirty and recheck QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); } - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - - // THEN - QCOMPARE(renderViewBuilder.lightGathererCacheNeedsToBeRebuilt(), true); - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - - // THEN - QCOMPARE(renderViewBuilder.renderableCacheNeedsToBeRebuilt(), true); - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - - // THEN - QCOMPARE(renderViewBuilder.computableCacheNeedsToBeRebuilt(), true); - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } } void checkCheckJobDependencies() @@ -365,13 +333,14 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 6); + QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob())); // Step 5 for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { @@ -487,21 +456,18 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLightGathererCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - renderViewBuilder.lightGathererJob()->run(); + renderer->lightGathererJob()->run(); // THEN - QCOMPARE(renderViewBuilder.lightGathererJob()->lights().size(), 2); - QVERIFY(renderViewBuilder.lightGathererJob()->takeEnvironmentLight() != nullptr); + QCOMPARE(renderer->lightGathererJob()->lights().size(), 2); + QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr); } void checkRenderableEntitiesFilteringExecution() @@ -510,20 +476,17 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - renderViewBuilder.renderableEntityFilterJob()->run(); + renderer->renderableEntityFilterJob()->run(); // THEN - QCOMPARE(renderViewBuilder.renderableEntityFilterJob()->filteredEntities().size(), 1); + QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1); } void checkComputableEntitiesFilteringExecution() @@ -532,20 +495,17 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); QVERIFY(leafNode != nullptr); // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setComputableCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - renderViewBuilder.computableEntityFilterJob()->run(); + renderer->computableEntityFilterJob()->run(); // THEN - QCOMPARE(renderViewBuilder.computableEntityFilterJob()->filteredEntities().size(), 1); + QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1); } void checkSyncRenderViewInitializationExecution() @@ -662,24 +622,28 @@ private Q_SLOTS: Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); layerFilter->addLayer(layer); Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id()); QVERIFY(leafNode != nullptr); // WHEN + renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); - renderViewBuilder.setRenderableCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); + renderer->renderableEntityFilterJob()->run(); + renderer->cacheRenderableEntitiesJob()->run(); + renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.renderableEntityFilterJob()->run(); renderViewBuilder.syncRenderViewPostInitializationJob()->run(); renderViewBuilder.filterEntityByLayerJob()->run(); - QVector renderableEntity = renderViewBuilder.renderableEntityFilterJob()->filteredEntities(); + QVector renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities(); QVector filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities(); // THEN -- cgit v1.2.3 From db9f0721c4406843766aab66d1cae170e76a237d Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 30 Oct 2019 15:13:18 +0100 Subject: Buffer: make sure we force allocate before doing partial updates Change-Id: I229f9bcd21a10c0a4cff5c4f559cd285a3e50276 Reviewed-by: Mike Krus --- tests/auto/render/buffer/tst_buffer.cpp | 55 +++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'tests') diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index 1b53efd33..fa1491914 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -157,6 +157,61 @@ private Q_SLOTS: QVERIFY(backendBuffer.pendingBufferUpdates().empty()); } + + void checkForceFullUploadOnFirstTime() + { + // GIVEN + Qt3DRender::Render::Buffer backendBuffer; + Qt3DRender::Render::BufferManager bufferManager; + TestRenderer renderer; + Qt3DRender::QBuffer frontendBuffer; + + QByteArray data("111456789\0"); + + frontendBuffer.setData(data); + frontendBuffer.updateData(1, QByteArray("23\0")); + + // THEN + QCOMPARE(frontendBuffer.data(), QByteArray("123456789\0")); + + // WHEN + backendBuffer.setManager(&bufferManager); + backendBuffer.setRenderer(&renderer); + simulateInitializationSync(&frontendBuffer, &backendBuffer); + + // THEN + QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1); + Qt3DRender::QBufferUpdate fullUpdate = backendBuffer.pendingBufferUpdates().first(); + QCOMPARE(fullUpdate.offset, -1); + QVERIFY(fullUpdate.data.isEmpty()); + QCOMPARE(frontendBuffer.data(), backendBuffer.data()); + + backendBuffer.pendingBufferUpdates().clear(); + + // WHEN + frontendBuffer.updateData(1, QByteArray("00\0")); + backendBuffer.syncFromFrontEnd(&frontendBuffer, false); + + // THEN + QCOMPARE(frontendBuffer.data(), QByteArray("100456789\0")); + QCOMPARE(backendBuffer.pendingBufferUpdates().size(), 1); + fullUpdate = backendBuffer.pendingBufferUpdates().first(); + QCOMPARE(fullUpdate.offset, 1); + QCOMPARE(fullUpdate.data, QByteArray("00\0")); + QCOMPARE(frontendBuffer.data(), backendBuffer.data()); + + // WHEN + frontendBuffer.updateData(1, QByteArray("22\0")); + backendBuffer.syncFromFrontEnd(&frontendBuffer, true); + + // THEN + QCOMPARE(frontendBuffer.data(), QByteArray("122456789\0")); + fullUpdate = backendBuffer.pendingBufferUpdates().first(); + QCOMPARE(fullUpdate.offset, -1); + QVERIFY(fullUpdate.data.isEmpty()); + QCOMPARE(frontendBuffer.data(), backendBuffer.data()); + } + void checkPropertyChanges() { // GIVEN -- cgit v1.2.3 From fae98c57264e78e62c5955559c7e513969462a79 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 28 Oct 2019 10:02:00 +0100 Subject: Fix SharedTexture manual tests Remove VideoPlayer thread, not needed and could yield to asserts if QOpenGLContext::makeCurrent is called from another thread than the one it was created with, depending on platforms and QApplication flags being set. Change-Id: Ic5d1858e5356b16293ee6298558dd7c60f3c86dd Reviewed-by: Mike Krus --- tests/manual/sharedtexture/main.cpp | 3 +-- tests/manual/sharedtexture/videoplayer.cpp | 28 +++++++--------------------- tests/manual/sharedtexture/videoplayer.h | 10 +++------- tests/manual/sharedtextureqml/main.cpp | 3 +-- 4 files changed, 12 insertions(+), 32 deletions(-) (limited to 'tests') diff --git a/tests/manual/sharedtexture/main.cpp b/tests/manual/sharedtexture/main.cpp index a85f90ee6..6f2ef42f2 100644 --- a/tests/manual/sharedtexture/main.cpp +++ b/tests/manual/sharedtexture/main.cpp @@ -137,8 +137,7 @@ int main(int argc, char* argv[]) // Multimedia player TextureWidget textureWidget; - VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget); - videoPlayer->start(); + VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget); textureWidget.resize(800, 600); textureWidget.show(); diff --git a/tests/manual/sharedtexture/videoplayer.cpp b/tests/manual/sharedtexture/videoplayer.cpp index f970116b5..2e52b85e0 100644 --- a/tests/manual/sharedtexture/videoplayer.cpp +++ b/tests/manual/sharedtexture/videoplayer.cpp @@ -57,8 +57,6 @@ TextureWidget::TextureWidget(QWidget *parent) : QOpenGLWidget(parent) , m_texture(QOpenGLTexture::Target2D) { - // Lock mutex so that we never process a frame until we have been initialized - m_mutex.lock(); } // Main thread @@ -104,14 +102,11 @@ void TextureWidget::initializeGL() qDebug() << Q_FUNC_INFO << context()->shareContext(); m_vao.create(); - // Allow rendering/frame acquisition to go on - m_mutex.unlock(); } // Main thread void TextureWidget::paintGL() { - QMutexLocker lock(&m_mutex); glViewport(0, 0, width(), height()); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); @@ -131,12 +126,8 @@ void TextureWidget::paintGL() m_shader.release(); } -// Video Player thread void TextureWidget::setVideoFrame(const QVideoFrame &frame) { - // Ensure we won't be rendering while we are processing the frame - QMutexLocker lock(&m_mutex); - QVideoFrame f = frame; // Map frame @@ -194,16 +185,14 @@ bool GLVideoSurface::present(const QVideoFrame &frame) return true; } -VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget) - : QThread(textureWidget) +VideoPlayer::VideoPlayer(TextureWidget *textureWidget) + : QObject(textureWidget) , m_player(new QMediaPlayer(nullptr, QMediaPlayer::VideoSurface)) , m_surface(new GLVideoSurface()) { - m_player->moveToThread(this); - m_player->setMedia(QUrl("https://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4")); + m_player->setMedia(QUrl("https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4")); // Tell player to render on GLVideoSurface - m_surface->moveToThread(this); m_player->setVideoOutput(m_surface.get()); // Display errors @@ -218,16 +207,13 @@ VideoPlayerThread::VideoPlayerThread(TextureWidget *textureWidget) m_player->play(); }); - // Start playing when thread starts - QObject::connect(this, &QThread::started, this, [this] { m_player->play(); }); - - // Direct connection between 2 objects living in different threads QObject::connect(m_surface.get(), &GLVideoSurface::onNewFrame, textureWidget, &TextureWidget::setVideoFrame, Qt::DirectConnection); + + // Start playing + m_player->play(); } -VideoPlayerThread::~VideoPlayerThread() +VideoPlayer::~VideoPlayer() { - exit(0); - wait(); } diff --git a/tests/manual/sharedtexture/videoplayer.h b/tests/manual/sharedtexture/videoplayer.h index 377ea57fe..a96cb16b1 100644 --- a/tests/manual/sharedtexture/videoplayer.h +++ b/tests/manual/sharedtexture/videoplayer.h @@ -48,9 +48,6 @@ ** ****************************************************************************/ -#include -#include - #include #include #include @@ -90,7 +87,6 @@ private: QOpenGLVertexArrayObject m_vao; QOpenGLShaderProgram m_shader; QOpenGLTexture m_texture; - QMutex m_mutex; }; @@ -108,12 +104,12 @@ Q_SIGNALS: }; -class VideoPlayerThread : public QThread +class VideoPlayer : public QObject { Q_OBJECT public: - VideoPlayerThread(TextureWidget *textureWidget); - ~VideoPlayerThread(); + VideoPlayer(TextureWidget *textureWidget); + ~VideoPlayer(); private: TextureWidget *m_textureWidget; diff --git a/tests/manual/sharedtextureqml/main.cpp b/tests/manual/sharedtextureqml/main.cpp index 5c7ae9cff..c0a79e6f8 100644 --- a/tests/manual/sharedtextureqml/main.cpp +++ b/tests/manual/sharedtextureqml/main.cpp @@ -108,8 +108,7 @@ int main(int argc, char* argv[]) // Multimedia player TextureWidget textureWidget; - VideoPlayerThread *videoPlayer = new VideoPlayerThread(&textureWidget); - videoPlayer->start(); + VideoPlayer *videoPlayer = new VideoPlayer(&textureWidget); textureWidget.resize(800, 600); textureWidget.show(); -- cgit v1.2.3 From 53a780960aa5245eb3e534e6bd0c268c050c52fa Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 8 Nov 2019 10:28:54 +0100 Subject: Uniform: use QVarLengthArray<16 ,float> instead of <4, float> This otherwise yield for lots of reallocations that could be avoided. The gains seem to be about 2/3% of cpu usage according the analysis with vTune. It does indeed mean that for smaller uniforms vec4, float, sampler we are wasting a bit of memory. The impact of this is likely to be unsignificant though. Change-Id: Id72c81a795bf9326ef48b170bb0806de9b430412 Reviewed-by: Mike Krus --- tests/auto/render/uniform/tst_uniform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/render/uniform/tst_uniform.cpp b/tests/auto/render/uniform/tst_uniform.cpp index 5f946afa3..d7775eb62 100644 --- a/tests/auto/render/uniform/tst_uniform.cpp +++ b/tests/auto/render/uniform/tst_uniform.cpp @@ -112,7 +112,7 @@ private Q_SLOTS: QCOMPARE(v.constData()[0], 572.0f); QCOMPARE(v.constData()[1], 355.0f); QCOMPARE(v.constData()[2], 383.0f); - QCOMPARE(v.constData()[4], 0.0f); + QCOMPARE(v.constData()[3], 0.0f); } { // GIVEN -- cgit v1.2.3 From 8de836c63eb0a0e484ae4c9e02f0a5f23ef49b65 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 8 Nov 2019 11:02:03 +0100 Subject: FilterProximityJob: only run it if our RV requires proximity filtering Which is only very rarely required by user applications. Avoid useless memory allocations every frame Change-Id: I69ea73ebfffdbe928f99333b4d1dd90cf4ada430 Reviewed-by: Mike Krus --- .../render/proximityfiltering/tst_proximityfiltering.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp index 1bed9fc44..ad12ffad0 100644 --- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -117,14 +117,20 @@ private Q_SLOTS: { Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity(); - Qt3DCore::QEntity *childEntity1 = new Qt3DCore::QEntity(rootEntity); - Qt3DCore::QEntity *childEntity2 = new Qt3DCore::QEntity(rootEntity); - Qt3DCore::QEntity *childEntity3 = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *targetEntity = new Qt3DCore::QEntity(rootEntity); + Qt3DCore::QEntity *childEntity1 = buildEntityAtDistance(50.0f, rootEntity); + Qt3DCore::QEntity *childEntity2 = buildEntityAtDistance(25.0f, rootEntity); + Qt3DCore::QEntity *childEntity3 = buildEntityAtDistance(75.0f, rootEntity); + + Qt3DRender::QProximityFilter *proximityFilter = new Qt3DRender::QProximityFilter(rootEntity); + proximityFilter->setDistanceThreshold(200.0f); + proximityFilter->setEntity(targetEntity); QTest::newRow("ShouldSelectAll") << rootEntity - << Qt3DCore::QNodeIdVector() + << (Qt3DCore::QNodeIdVector() << proximityFilter->id()) << (Qt3DCore::QNodeIdVector() << rootEntity->id() + << targetEntity->id() << childEntity1->id() << childEntity2->id() << childEntity3->id() -- cgit v1.2.3 From 50db67eb310fba162f73ac6fdf28a8457ce50b21 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 18 Oct 2019 14:35:40 +0200 Subject: PackUniformHash to QVector Surprisingly it's hard to notice its effect in the speed of execution, frame preparation looks to be more or less the same with the profiler. However with vtune, the profiling traces show a huge difference with QHash, mainly in time spent allocating memory. It shows a noticeable reduction in CPU usage. On bigscene-cpp with 600 entities QHash -> On a 158s run, CPU time is 112s (70%) free accounts for 26s (23%), malloc 24s (21%) QVector -> On a 190s run, CPU time is 110s (58%) free accounts for 5s (4.5%), malloc 4.7s (4.2%) Change-Id: I880d44b1acf7f051e479ed356864c3caf407f23f Reviewed-by: Mike Krus --- tests/auto/render/renderviews/tst_renderviews.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index 17995659b..1558b68c9 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -51,16 +51,11 @@ void compareShaderParameterPacks(const ShaderParameterPack &t1, const PackUniformHash hash1 = t1.uniforms(); const PackUniformHash hash2 = t2.uniforms(); - QCOMPARE(hash1.size(), hash2.size()); + QCOMPARE(hash1.keys.size(), hash2.keys.size()); - auto it = hash1.constBegin(); - const auto end = hash1.constEnd(); - - while (it != end) { - const auto h2It = hash2.find(it.key()); - QVERIFY(h2It != hash2.cend()); - QCOMPARE(it.value(), h2It.value()); - ++it; + for (int i = 0, m = hash1.keys.size(); i < m; ++i) { + const int key = hash1.keys.at(i); + QCOMPARE(hash1.value(key), hash2.value(key)); } } -- cgit v1.2.3 From a10e61dce43a0e40b71648147651817953111cbb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 25 Nov 2019 12:58:21 +0100 Subject: Avoid initializing QFlags with 0 or nullptr It is being deprecated. Change-Id: Idb6e794be1a26a3ca7c1d19ac1f47e4a0125f11b Reviewed-by: Allan Sandfeld Jensen --- tests/auto/render/commons/testrenderer.cpp | 8 ++------ tests/auto/render/commons/testrenderer.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/commons/testrenderer.cpp b/tests/auto/render/commons/testrenderer.cpp index 277b2b99b..5a36fecf2 100644 --- a/tests/auto/render/commons/testrenderer.cpp +++ b/tests/auto/render/commons/testrenderer.cpp @@ -30,11 +30,7 @@ QT_BEGIN_NAMESPACE -TestRenderer::TestRenderer() - : m_changes(0) - , m_managers(nullptr) -{ -} +TestRenderer::TestRenderer() = default; TestRenderer::~TestRenderer() { @@ -60,7 +56,7 @@ void TestRenderer::clearDirtyBits(Qt3DRender::Render::AbstractRenderer::BackendN void TestRenderer::resetDirty() { - m_changes = 0; + m_changes = {}; } QVariant TestRenderer::executeCommand(const QStringList &args) diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 8d27998a0..f3798e5f8 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -90,7 +90,7 @@ public: protected: Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes; - Qt3DRender::Render::NodeManagers *m_managers; + Qt3DRender::Render::NodeManagers *m_managers = nullptr; }; QT_END_NAMESPACE -- cgit v1.2.3 From 568b2d62e6e07b40d602bcd2a1c2e8e566c41b9f Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 2 Dec 2019 19:49:40 +0000 Subject: Revert "Fix post FF API changes" 84766ed9098f10efc53e4e43a75eef38fce7fbf6 Change-Id: I12341ec1b7bc68a7586c6671aa7b8f21caed17e0 Reviewed-by: Paul Lemire --- tests/auto/core/common/testpostmanarbiter.h | 1 - tests/auto/core/nodes/tst_nodes.cpp | 12 +++++------- tests/auto/render/raycastingjob/tst_raycastingjob.cpp | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/common/testpostmanarbiter.h b/tests/auto/core/common/testpostmanarbiter.h index 6649c7bbe..cecc24f93 100644 --- a/tests/auto/core/common/testpostmanarbiter.h +++ b/tests/auto/core/common/testpostmanarbiter.h @@ -28,7 +28,6 @@ #include #include -#include QT_BEGIN_NAMESPACE diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index b5291cab7..87f66bab2 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -531,7 +530,7 @@ public: void syncDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QBackendNode *backend, bool firstTime) const override { - Q_UNUSED(backend) + Q_UNUSED(backend); auto q = q_func(); if (firstTime) q->allNodes.insert(node->id(), node); @@ -542,11 +541,10 @@ public: TestAspect::TestAspect(QObject *parent) : TestAspect(*new TestAspectPrivate, parent) { - Q_D(TestAspect); - d->registerBackendType(QSharedPointer::create(this)); - d->registerBackendType(QSharedPointer::create(this)); - d->registerBackendType(QSharedPointer::create(this)); - d->registerBackendType(QSharedPointer::create(this)); + registerBackendType(QSharedPointer::create(this)); + registerBackendType(QSharedPointer::create(this)); + registerBackendType(QSharedPointer::create(this)); + registerBackendType(QSharedPointer::create(this)); } TestAspect::TestAspect(TestAspectPrivate &dd, QObject *parent) diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp index eaf85f5b6..1ff899936 100644 --- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp +++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp @@ -285,7 +285,7 @@ private Q_SLOTS: initializeJob(&rayCastingJob, test.data()); bool earlyReturn = !rayCastingJob.runHelper(); - Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager()); + rayCastingJob.postFrame(test->aspectManager()); QCoreApplication::processEvents(); // THEN @@ -345,7 +345,7 @@ private Q_SLOTS: initializeJob(&rayCastingJob, test.data()); bool earlyReturn = !rayCastingJob.runHelper(); - Qt3DCore::QAspectJobPrivate::get(&rayCastingJob)->postFrame(test->aspectManager()); + rayCastingJob.postFrame(test->aspectManager()); QCoreApplication::processEvents(); // THEN -- cgit v1.2.3 From 00e0783992a4326fcca93e118edb9a3ed09fd5a4 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 2 Dec 2019 20:22:44 +0000 Subject: Fix compile warnings Change-Id: Idb253d8cb42809ae21cfbbda70d6b6c75891070f Reviewed-by: Paul Lemire --- tests/auto/animation/animationutils/tst_animationutils.cpp | 4 ++-- tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp | 12 ++++++------ tests/auto/core/threadpooler/tst_threadpooler.cpp | 14 +++++++------- .../render/proximityfiltering/tst_proximityfiltering.cpp | 2 +- tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp | 2 +- tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp | 1 + .../tst_vsyncframeadvanceservice.cpp | 2 +- 7 files changed, 19 insertions(+), 18 deletions(-) (limited to 'tests') diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 385398bd1..463656557 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -1047,7 +1047,7 @@ private Q_SLOTS: mapping.type = static_cast(QVariant::Vector3D); mapping.channelIndices = QVector() << 0 << 1 << 2; mapping.callback = &callback; - mapping.callbackFlags = 0; + mapping.callbackFlags = {}; mappingData.push_back(mapping); channelResults = QVector() << 1.0f << 2.0f << 3.0f; @@ -1073,7 +1073,7 @@ private Q_SLOTS: mapping.type = static_cast(QVariant::Double); mapping.channelIndices = QVector() << 0; mapping.callback = &callback; - mapping.callbackFlags = 0; + mapping.callbackFlags = {}; mappingData.push_back(mapping); channelResults = QVector() << 1.0f; diff --git a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp index 4bc04fafa..7d8f6eed6 100644 --- a/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp +++ b/tests/auto/core/qcircularbuffer/tst_qcircularbuffer.cpp @@ -166,13 +166,13 @@ void tst_QCircularBuffer::construction() QVERIFY(circ4.size() == 2); QVERIFY(circ4.at(0) == 10); QVERIFY(circ4.at(1) == 10); - QVERIFY(circ4.refCount().load() == 1); + QVERIFY(circ4.refCount().loadRelaxed() == 1); // Copy construct from circ4. Both circ4 and circ5 should now have a // refCount() of 2 since we are using implicit sharing. QCircularBuffer circ5(circ4); - QVERIFY(circ4.refCount().load() == 2); - QVERIFY(circ5.refCount().load() == 2); + QVERIFY(circ4.refCount().loadRelaxed() == 2); + QVERIFY(circ5.refCount().loadRelaxed() == 2); QVERIFY(circ5.capacity() == 5); QVERIFY(circ5.size() == 2); QVERIFY(circ5.at(0) == 10); @@ -199,7 +199,7 @@ void tst_QCircularBuffer::destruction() cir->append(MyComplexType(2)); cir->append(MyComplexType(3)); cir->remove(0); - Q_UNUSED(cir); + Q_UNUSED(cir) // Check that the dtor was called 2 times fewer than the constructor. // At this stage will still have 2 items in the circular buffer. @@ -208,7 +208,7 @@ void tst_QCircularBuffer::destruction() // Destroy the circular buffer and check that the active count // is 0. (Same number of calls to dtor as have been made to the constructors) delete cir; - cir = 0; + cir = nullptr; QVERIFY(MyComplexType::ms_activeCount == 0); } @@ -273,7 +273,7 @@ void tst_QCircularBuffer::clear() circ.clear(); QVERIFY(circ.size() == 0); QVERIFY(circ.capacity() == 3); - QVERIFY(circ.refCount().load() == 1); + QVERIFY(circ.refCount().loadRelaxed() == 1); } void tst_QCircularBuffer::contains() diff --git a/tests/auto/core/threadpooler/tst_threadpooler.cpp b/tests/auto/core/threadpooler/tst_threadpooler.cpp index a656c25c1..cfe3480ee 100644 --- a/tests/auto/core/threadpooler/tst_threadpooler.cpp +++ b/tests/auto/core/threadpooler/tst_threadpooler.cpp @@ -195,13 +195,13 @@ void tst_ThreadPooler::defaultPerThread() // GIVEN QAtomicInt callCounter; int maxThreadCount = QThread::idealThreadCount(); - callCounter.store(0); + callCounter.storeRelaxed(0); // WHEN m_jobManager->waitForPerThreadFunction(perThreadFunction, &callCounter); // THEN - QVERIFY(maxThreadCount == callCounter.load()); + QVERIFY(maxThreadCount == callCounter.loadRelaxed()); } void tst_ThreadPooler::defaultAspectQueue() @@ -210,7 +210,7 @@ void tst_ThreadPooler::defaultAspectQueue() QAtomicInt callCounter; int value = 0; // Not used in this test QVector > jobList; - callCounter.store(0); + callCounter.storeRelaxed(0); const int jobCount = 5; // WHEN @@ -223,7 +223,7 @@ void tst_ThreadPooler::defaultAspectQueue() m_jobManager->waitForAllJobs(); // THEN - QVERIFY(jobCount == callCounter.load()); + QVERIFY(jobCount == callCounter.loadRelaxed()); } /* @@ -236,7 +236,7 @@ void tst_ThreadPooler::doubleAspectQueue() QAtomicInt callCounter; int value = 0; // Not used in this test QVector > jobList; - callCounter.store(0); + callCounter.storeRelaxed(0); const int jobCount = 3; // WHEN @@ -258,7 +258,7 @@ void tst_ThreadPooler::doubleAspectQueue() m_jobManager->waitForAllJobs(); // THEN - QVERIFY(jobCount * 2 == callCounter.load()); + QVERIFY(jobCount * 2 == callCounter.loadRelaxed()); } /* @@ -335,7 +335,7 @@ public: quint64 globalAtomicValue() const { - return m_globalAtomic.load(); + return m_globalAtomic.loadRelaxed(); } private: diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp index ad12ffad0..1b65388af 100644 --- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -50,7 +50,7 @@ Qt3DCore::QEntity *buildEntityAtDistance(float distance, Qt3DCore::QEntity *pare // create geometry with a valid bounding volume - a single point is sufficient auto geometry = new Qt3DRender::QGeometry; - auto vertexBuffer = new Qt3DRender::QBuffer(Qt3DRender::QBuffer::VertexBuffer, geometry); + auto vertexBuffer = new Qt3DRender::QBuffer(geometry); auto positionAttribute = new Qt3DRender::QAttribute; positionAttribute->setName(Qt3DRender::QAttribute::defaultPositionAttributeName()); diff --git a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp index 24febdac4..6116e031e 100644 --- a/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp +++ b/tests/auto/render/qframegraphnode/tst_qframegraphnode.cpp @@ -94,7 +94,7 @@ private Q_SLOTS: { Qt3DRender::QFrameGraphNode *nodeWithNestedChildren = new MyFrameGraphNode(); Qt3DRender::QFrameGraphNode *child = new MyFrameGraphNode(nodeWithNestedChildren); - Qt3DCore::QNode *dummy = new Qt3DCore::QNode(nodeWithNestedChildren); + new Qt3DCore::QNode(nodeWithNestedChildren); Qt3DRender::QFrameGraphNode *grandChild = new MyFrameGraphNode(nodeWithNestedChildren); QVector childIds = {child->id(), grandChild->id()}; QTest::newRow("nodeWithNestedChildren") << nodeWithNestedChildren << childIds << true << 4; diff --git a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp index 7a08fe018..24dbe514a 100644 --- a/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp +++ b/tests/auto/render/shaderbuilder/tst_shaderbuilder.cpp @@ -560,6 +560,7 @@ private slots: QVERIFY(!Qt3DRender::Render::ShaderBuilder::getPrototypeNames().isEmpty()); QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); QFETCH(Qt3DRender::QShaderProgram::ShaderType, notificationType); + Q_UNUSED(notificationType) const auto gl3Api = []{ auto api = Qt3DRender::GraphicsApiFilterData(); diff --git a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp index 1238f1800..aafdb36f7 100644 --- a/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp +++ b/tests/auto/render/vsyncframeadvanceservice/tst_vsyncframeadvanceservice.cpp @@ -71,7 +71,7 @@ private: bool isReadyToSubmit() { m_submitSemaphore.acquire(1); - return m_running.load() == 1; + return m_running.loadRelaxed() == 1; } Qt3DRender::Render::VSyncFrameAdvanceService *m_tickService; -- cgit v1.2.3 From 96b1b9e3e198e751bb96eeb279106862ca38e7d7 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 4 Dec 2019 08:14:29 +0100 Subject: Fix OnDemand rendering with Scene3D When using OnDemand rendering, Scene3D would lock if nothing in the scene were to change. By being blocked, it would also not process jobs for other aspects (input, logics). That would prevent things like a CameraController from running, which in turn would make it impossible to move the camera and trigger a change in the scene to request rendering. Additionally, Scene3D would ignore whether the Qt3D renderer actually needed rendering or not as it was watching on its own the changeArbiter for changes to decide whether rendering was required or not. This would ignore the case where Qt3D needs multiple frames to render a correct frame (e.g loading buffers, shaders at frame n, rebuilding commands at frame n+1) Scene3D now asks the Qt3D renderer by calling the shouldRender() function to decide whether rendering is needed or not, in addition to watching the changeArbiter. Regardless of whether rendering is needed, it now let each aspect process jobs. This ensures things like FrameAction/Input are processed. Then, Scene3D decides whether full rendering is required or whether it only has to be called to allow the Qt3D simulation loop to proceed for the next frame. If the latter, it does it so as not to have QtQuick trigger a redraw. Change-Id: I870f773c224286d6b7ec0f6045319e51e09cbf8e Task-number: QTBUG-80521 Reviewed-by: Mike Krus --- tests/auto/render/commons/testrenderer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 8d27998a0..e1ee329f4 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -55,7 +55,7 @@ public: void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers); } void cleanGraphicsResources() override {} bool isRunning() const override { return true; } - bool shouldRender() override { return true; } + bool shouldRender() const override { return true; } void skipNextFrame() override {} QVector preRenderingJobs() override { return QVector(); } QVector renderBinJobs() override { return QVector(); } -- cgit v1.2.3 From 3019497559328d2fd0c0c9548f512fba9fe1f94e Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 27 Sep 2019 07:16:58 +0200 Subject: Shader: record standard uniform at loading time Avoids having to check for each uniform (for each frame, each geometry) whether it is a standard uniform or a user defined one. Change-Id: I76cff7869aacc1343a9acf991f8035b8118581ed Reviewed-by: Mike Krus --- tests/auto/core/qaspectengine/tst_qaspectengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp index eb20536e6..244077d46 100644 --- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp +++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp @@ -168,7 +168,7 @@ private Q_SLOTS: engine.setRootEntity(entity); QEventLoop eventLoop; - QTimer::singleShot(100, &eventLoop, SLOT(quit())); + QTimer::singleShot(1000, &eventLoop, SLOT(quit())); eventLoop.exec(); // THEN -- cgit v1.2.3 From 69789d0184ffa54c1760ad5204bb4539c9399753 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Sat, 7 Dec 2019 13:03:58 +0000 Subject: Fix picking with primitive restart Task-number: QTBUG-71919 Change-Id: If7923fab6c43f5d7139d1bbdceb73c17bf489099 Reviewed-by: Paul Lemire --- .../render/trianglevisitor/tst_trianglevisitor.cpp | 26 +++++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp index 8dfda0eea..66f67e08a 100644 --- a/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp +++ b/tests/auto/render/trianglevisitor/tst_trianglevisitor.cpp @@ -454,7 +454,7 @@ private Q_SLOTS: simulateInitializationSync(dataBuffer.data(), backendBuffer); QByteArray indexData; - indexData.resize(sizeof(uint) * 3 * 4); + indexData.resize(sizeof(uint) * 4 * 4); uint *iDataPtr = reinterpret_cast(indexData.data()); iDataPtr[0] = 0; iDataPtr[1] = 1; @@ -468,6 +468,10 @@ private Q_SLOTS: iDataPtr[9] = 4; iDataPtr[10] = 3; iDataPtr[11] = 2; + iDataPtr[12] = static_cast(-1); + iDataPtr[13] = 0; + iDataPtr[14] = 1; + iDataPtr[15] = 2; indexDataBuffer->setData(indexData); Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); @@ -486,7 +490,7 @@ private Q_SLOTS: indexAttribute->setBuffer(indexDataBuffer.data()); indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); - indexAttribute->setCount(3*4); + indexAttribute->setCount(4*4); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); geometry->addAttribute(positionAttribute.data()); @@ -494,6 +498,8 @@ private Q_SLOTS: geometryRenderer->setGeometry(geometry); geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleStrip); + geometryRenderer->setPrimitiveRestartEnabled(true); + geometryRenderer->setRestartIndexValue(-1); Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); backendAttribute->setRenderer(&renderer); @@ -516,7 +522,7 @@ private Q_SLOTS: visitor.apply(backendRenderer, Qt3DCore::QNodeId()); // THEN - QVERIFY(visitor.triangleCount() == 8); + QCOMPARE(visitor.triangleCount(), 9U); QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); QVERIFY(visitor.verifyTriangle(1, 3,2,1, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(1,0,0))); QVERIFY(visitor.verifyTriangle(2, 4,3,2, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,1,0))); @@ -525,6 +531,7 @@ private Q_SLOTS: QVERIFY(visitor.verifyTriangle(5, 4,0,1, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(1,0,0))); QVERIFY(visitor.verifyTriangle(6, 3,4,0, Vector3D(0,0,1), Vector3D(1,0,0), Vector3D(0,0,1))); QVERIFY(visitor.verifyTriangle(7, 2,3,4, Vector3D(0,1,0), Vector3D(0,0,1), Vector3D(1,0,0))); + QVERIFY(visitor.verifyTriangle(8, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTriangleFan() @@ -643,7 +650,7 @@ private Q_SLOTS: simulateInitializationSync(dataBuffer.data(), backendBuffer); QByteArray indexData; - indexData.resize(sizeof(uint) * 3 * 2); + indexData.resize(sizeof(uint) * 10); uint *iDataPtr = reinterpret_cast(indexData.data()); iDataPtr[0] = 0; iDataPtr[1] = 1; @@ -651,6 +658,10 @@ private Q_SLOTS: iDataPtr[3] = 3; iDataPtr[4] = 4; iDataPtr[5] = 5; + iDataPtr[6] = static_cast(-1); + iDataPtr[7] = 0; + iDataPtr[8] = 1; + iDataPtr[9] = 2; indexDataBuffer->setData(indexData); Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); @@ -669,7 +680,7 @@ private Q_SLOTS: indexAttribute->setBuffer(indexDataBuffer.data()); indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); - indexAttribute->setCount(3*2); + indexAttribute->setCount(10); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); geometry->addAttribute(positionAttribute.data()); @@ -677,6 +688,8 @@ private Q_SLOTS: geometryRenderer->setGeometry(geometry); geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::TriangleFan); + geometryRenderer->setPrimitiveRestartEnabled(true); + geometryRenderer->setRestartIndexValue(-1); Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); backendAttribute->setRenderer(&renderer); @@ -699,11 +712,12 @@ private Q_SLOTS: visitor.apply(backendRenderer, Qt3DCore::QNodeId()); // THEN - QVERIFY(visitor.triangleCount() == 4); + QCOMPARE(visitor.triangleCount(), 5U); QVERIFY(visitor.verifyTriangle(0, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); QVERIFY(visitor.verifyTriangle(1, 3,2,0, Vector3D(0,0,1), Vector3D(0,1,0), Vector3D(0,0,1))); QVERIFY(visitor.verifyTriangle(2, 4,3,0, Vector3D(1,0,0), Vector3D(0,0,1), Vector3D(0,0,1))); QVERIFY(visitor.verifyTriangle(3, 5,4,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); + QVERIFY(visitor.verifyTriangle(4, 2,1,0, Vector3D(0,1,0), Vector3D(1,0,0), Vector3D(0,0,1))); } void testVisitTrianglesAdjacency() -- cgit v1.2.3 From 6e448dd5918c70ddfd0d52f62522fa49c02e8ba8 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 2 Dec 2019 17:19:03 +0000 Subject: Deprecate message API Deprecates the message classes and the public APIs to send/receive them. (deprecates the constructors as deprecating classes breaks syncqt) Change-Id: I4908f15c3c5f1d63969a0f2e11f6ecb22e2e3748 Reviewed-by: Mike Krus --- tests/auto/core/qaspectengine/tst_qaspectengine.cpp | 2 +- tests/auto/render/entity/tst_entity.cpp | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp index 244077d46..4565f0d69 100644 --- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp +++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp @@ -179,7 +179,7 @@ private Q_SLOTS: // WHEN // we set an empty/null scene root... engine.setRootEntity(QEntityPtr()); - QTimer::singleShot(1000, &eventLoop, SLOT(quit())); + QTimer::singleShot(600, &eventLoop, SLOT(quit())); // ...and allow events to process... eventLoop.exec(); diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index e3b8e756e..93f2614b8 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -35,7 +35,6 @@ #include #include -#include #include #include @@ -151,11 +150,6 @@ private slots: nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntity.id()); nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntityChild.id()); -// TODOSYNC clean up -// // Send children added event to entity -// const auto addEntityChange = QPropertyNodeAddedChangePtr::create(dummyFrontendEntity.id(), &dummyFrontendEntityChild); -// entity.sceneChangeEvent(addEntityChange); - // THEN QVERIFY(!entity.componentUuid().isNull()); QVERIFY(!entity.componentUuid().isNull()); -- cgit v1.2.3 From e5f41230d2fa1cdc126785f396e5a57cee728341 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 10 Dec 2019 14:44:08 +0100 Subject: Skip shouldNotCrashInNormalStartupShutdownSequence The test is flaky on macOS 10.12 and 10.13. As it usually times out, a blacklist entry won't help. Blacklisting merely ignores the result, but doesn't prevent the test watchdog from killing the process. Task-number: QTBUG-80660 Change-Id: I6aec979e7437700e4e6596241f135622d99fd3be Reviewed-by: Simon Hausmann --- tests/auto/core/qaspectengine/tst_qaspectengine.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests') diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp index 244077d46..2f16bf7c6 100644 --- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp +++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp @@ -146,6 +146,10 @@ private Q_SLOTS: void shouldNotCrashInNormalStartupShutdownSequence() { +#ifdef Q_OS_MACOS + QSKIP("Test frequently times out. See QTBUG-80660."); +#endif + // GIVEN // An initialized aspect engine... QAspectEngine engine; -- cgit v1.2.3 From ecd193d7b5788fca8b478a02068060a078dc5738 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 9 Dec 2019 15:10:53 +0000 Subject: Fix picking with primitive restart for line loops Previous fix was not closing the loop on every primitive, just the last one. Task-number: QTBUG-71919 Change-Id: I22d52258477b0c4777118ee36a0b3868da982885 Reviewed-by: Volker Enderlein Reviewed-by: Paul Lemire --- .../render/segmentvisitor/tst_segmentvisitor.cpp | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp index 4db12136a..fc65d0854 100644 --- a/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp +++ b/tests/auto/render/segmentvisitor/tst_segmentvisitor.cpp @@ -426,12 +426,15 @@ private Q_SLOTS: simulateInitializationSync(dataBuffer.data(), backendBuffer); QByteArray indexData; - indexData.resize(sizeof(uint) * 2 * 4); + indexData.resize(sizeof(uint) * 7); uint *iDataPtr = reinterpret_cast(indexData.data()); iDataPtr[0] = 0; iDataPtr[1] = 1; iDataPtr[2] = 2; iDataPtr[3] = 3; + iDataPtr[4] = static_cast(-1); + iDataPtr[5] = 0; + iDataPtr[6] = 1; indexDataBuffer->setData(indexData); Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); @@ -450,7 +453,7 @@ private Q_SLOTS: indexAttribute->setBuffer(indexDataBuffer.data()); indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); - indexAttribute->setCount(4); + indexAttribute->setCount(7); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); geometry->addAttribute(positionAttribute.data()); @@ -458,6 +461,8 @@ private Q_SLOTS: geometryRenderer->setGeometry(geometry); geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineStrip); + geometryRenderer->setPrimitiveRestartEnabled(true); + geometryRenderer->setRestartIndexValue(-1); Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); backendAttribute->setRenderer(&renderer); @@ -480,10 +485,11 @@ private Q_SLOTS: visitor.apply(backendRenderer, Qt3DCore::QNodeId()); // THEN - QCOMPARE(visitor.segmentCount(), uint(3)); + QCOMPARE(visitor.segmentCount(), uint(4)); QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); + QVERIFY(visitor.verifySegment(3, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); } void testVisitLineLoop() @@ -588,12 +594,16 @@ private Q_SLOTS: simulateInitializationSync(dataBuffer.data(), backendBuffer); QByteArray indexData; - indexData.resize(sizeof(uint) * 2 * 4); + indexData.resize(sizeof(uint) * 8); uint *iDataPtr = reinterpret_cast(indexData.data()); iDataPtr[0] = 0; iDataPtr[1] = 1; iDataPtr[2] = 2; iDataPtr[3] = 3; + iDataPtr[4] = static_cast(-1); + iDataPtr[5] = 0; + iDataPtr[6] = 1; + iDataPtr[7] = 2; indexDataBuffer->setData(indexData); Buffer *backendIndexBuffer = nodeManagers->bufferManager()->getOrCreateResource(indexDataBuffer->id()); @@ -612,7 +622,7 @@ private Q_SLOTS: indexAttribute->setBuffer(indexDataBuffer.data()); indexAttribute->setVertexBaseType(Qt3DRender::QAttribute::UnsignedInt); - indexAttribute->setCount(4); + indexAttribute->setCount(8); indexAttribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); geometry->addAttribute(positionAttribute.data()); @@ -620,6 +630,8 @@ private Q_SLOTS: geometryRenderer->setGeometry(geometry); geometryRenderer->setPrimitiveType(Qt3DRender::QGeometryRenderer::LineLoop); + geometryRenderer->setPrimitiveRestartEnabled(true); + geometryRenderer->setRestartIndexValue(-1); Attribute *backendAttribute = nodeManagers->attributeManager()->getOrCreateResource(positionAttribute->id()); backendAttribute->setRenderer(&renderer); @@ -642,11 +654,14 @@ private Q_SLOTS: visitor.apply(backendRenderer, Qt3DCore::QNodeId()); // THEN - QCOMPARE(visitor.segmentCount(), uint(4)); + QCOMPARE(visitor.segmentCount(), uint(7)); QVERIFY(visitor.verifySegment(0, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); QVERIFY(visitor.verifySegment(1, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); QVERIFY(visitor.verifySegment(2, 2,3, Vector3D(1,1,0), Vector3D(0,1,0))); QVERIFY(visitor.verifySegment(3, 3,0, Vector3D(0,1,0), Vector3D(0,0,0))); + QVERIFY(visitor.verifySegment(4, 0,1, Vector3D(0,0,0), Vector3D(1,0,0))); + QVERIFY(visitor.verifySegment(5, 1,2, Vector3D(1,0,0), Vector3D(1,1,0))); + QVERIFY(visitor.verifySegment(6, 2,0, Vector3D(1,1,0), Vector3D(0,0,0))); } void testVisitLineAdjacency() -- cgit v1.2.3 From ef886f79f99cdae94da8bf5a4ca6e94164d56677 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 5 Dec 2019 10:33:32 +0000 Subject: Make tracing a runtime option - Moved most of the code QSystemInformationService (private class for now) - Tracing can be enabled by setting QT3D_TRACE_ENABLED or calling QSystemInformationService::setTraceEnabled(bool) - Introduced QTaskLogger class to easy logging (RAII) Change-Id: I2a3e08e4371fcee3e9ef3cf575725f13f57d1a94 Reviewed-by: Paul Lemire --- tests/auto/core/qservicelocator/tst_qservicelocator.cpp | 14 +++++--------- tests/auto/core/threadpooler/tst_threadpooler.cpp | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp index cde9834b4..04e6881aa 100644 --- a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp +++ b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp @@ -54,9 +54,6 @@ public: DummySystemInfoService() : QSystemInformationService(QStringLiteral("Dummy System Information Service")) {} - - QStringList aspectNames() const final { return QStringList(); } - int threadPoolThreadCount() const final { return 4; } }; @@ -90,8 +87,8 @@ void tst_QServiceLocator::defaultServices() QSystemInformationService *sysInfo = locator.systemInformation(); QVERIFY(sysInfo != nullptr); - QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service")); - QVERIFY(sysInfo->threadPoolThreadCount() == 0); + QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service")); + QVERIFY(sysInfo->threadPoolThreadCount() != 0); } void tst_QServiceLocator::addRemoveDefaultService() @@ -105,7 +102,6 @@ void tst_QServiceLocator::addRemoveDefaultService() // Get the service from the locator and check it works as expected QSystemInformationService *service = locator.systemInformation(); QVERIFY(service == dummy.data()); - QVERIFY(service->threadPoolThreadCount() == 4); // Ensure the other default services work QOpenGLInformationService *glInfo = locator.openGLInformation(); @@ -118,7 +114,7 @@ void tst_QServiceLocator::addRemoveDefaultService() QVERIFY(locator.serviceCount() == QServiceLocator::DefaultServiceCount); // Check the dummy service still exists - QVERIFY(dummy->threadPoolThreadCount() == 4); + QVERIFY(!dummy.isNull()); } void tst_QServiceLocator::addRemoveUserService() @@ -138,8 +134,8 @@ void tst_QServiceLocator::addRemoveUserService() // Ensure the default services work QSystemInformationService *sysInfo = locator.systemInformation(); QVERIFY(sysInfo != nullptr); - QVERIFY(sysInfo->description() == QStringLiteral("Null System Information Service")); - QVERIFY(sysInfo->threadPoolThreadCount() == 0); + QVERIFY(sysInfo->description() == QStringLiteral("Default System Information Service")); + QVERIFY(sysInfo->threadPoolThreadCount() != 0); // Remove custom service locator.unregisterServiceProvider(dummy->type()); diff --git a/tests/auto/core/threadpooler/tst_threadpooler.cpp b/tests/auto/core/threadpooler/tst_threadpooler.cpp index cfe3480ee..289f0b103 100644 --- a/tests/auto/core/threadpooler/tst_threadpooler.cpp +++ b/tests/auto/core/threadpooler/tst_threadpooler.cpp @@ -182,7 +182,7 @@ void massTestFunction(QVector3D *data) void tst_ThreadPooler::initTestCase() { - m_jobManager = new JobManager(this); + m_jobManager = new JobManager(nullptr); } void tst_ThreadPooler::cleanupTestCase() -- cgit v1.2.3 From 7d62c1448721a261c053a3d8adabc21787f1d955 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 5 Dec 2019 15:07:58 +0000 Subject: Implement getting list of aspects from system information class Change-Id: I999dfbb5c139ff8af2b1de9255f76ac132ae2dc0 Reviewed-by: Paul Lemire --- tests/auto/core/qaspectengine/tst_qaspectengine.cpp | 6 +++--- tests/auto/core/qservicelocator/tst_qservicelocator.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp index 4565f0d69..466e103ec 100644 --- a/tests/auto/core/qaspectengine/tst_qaspectengine.cpp +++ b/tests/auto/core/qaspectengine/tst_qaspectengine.cpp @@ -243,21 +243,21 @@ private Q_SLOTS: // THEN QCOMPARE(engine.executeCommand("list aspects").toString(), - QString("Loaded aspects:\n * fake")); + QString("fake")); // WHEN engine.registerAspect("otherfake"); // THEN QCOMPARE(engine.executeCommand("list aspects").toString(), - QString("Loaded aspects:\n * fake\n * otherfake")); + QString("fake\notherfake")); // WHEN engine.registerAspect(new FakeAspect3); // THEN QCOMPARE(engine.executeCommand("list aspects").toString(), - QString("Loaded aspects:\n * fake\n * otherfake\n * ")); + QString("fake\notherfake\n")); } void shouldDelegateCommandsToAspects() diff --git a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp index 04e6881aa..40f0610df 100644 --- a/tests/auto/core/qservicelocator/tst_qservicelocator.cpp +++ b/tests/auto/core/qservicelocator/tst_qservicelocator.cpp @@ -52,7 +52,7 @@ class DummySystemInfoService : public QSystemInformationService { public: DummySystemInfoService() - : QSystemInformationService(QStringLiteral("Dummy System Information Service")) + : QSystemInformationService(nullptr, QStringLiteral("Dummy System Information Service")) {} }; -- cgit v1.2.3 From 22eccf3a95279b85c849c6a49a0a804beb58e2c5 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Fri, 6 Dec 2019 15:49:36 +0000 Subject: Use jobsDone to sync render capture back to frontend Removes the jobs who's only purpose was to send a message to the frontend. Now added a jobsDone() call to render which is called from main thread when jobs are completed, so it's safe to sync data to frontend. Added a task trace for the backend to front end synching. Change-Id: I587462bea353c5d5a0065b542adcacef4dedb05f Reviewed-by: Paul Lemire --- tests/auto/render/commons/testrenderer.h | 15 ++-- tests/auto/render/render.pro | 1 - tests/auto/render/renderer/tst_renderer.cpp | 10 --- .../sendrendercapturejob/sendrendercapturejob.pro | 12 --- .../tst_sendrendercapturejob.cpp | 85 ---------------------- tests/manual/rendercapture-qml/main.qml | 2 +- 6 files changed, 9 insertions(+), 116 deletions(-) delete mode 100644 tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro delete mode 100644 tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp (limited to 'tests') diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index f3798e5f8..8cab7edfc 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -42,33 +42,34 @@ public: void dumpInfo() const override {} API api() const override { return AbstractRenderer::OpenGL; } qint64 time() const override { return 0; } - void setTime(qint64 time) override { Q_UNUSED(time); } + void setTime(qint64 time) override { Q_UNUSED(time) } void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override { m_managers = m; } - void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services); } - void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed); } + void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services) } + void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed) } Qt3DRender::Render::NodeManagers *nodeManagers() const override { return m_managers; } Qt3DCore::QServiceLocator *services() const override { return nullptr; } void initialize() override {} void shutdown() override {} void releaseGraphicsResources() override {} void render() override {} - void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers); } + void doRender(bool swapBuffers) override { Q_UNUSED(swapBuffers) } void cleanGraphicsResources() override {} bool isRunning() const override { return true; } bool shouldRender() override { return true; } void skipNextFrame() override {} + void jobsDone(Qt3DCore::QAspectManager *manager) override { Q_UNUSED(manager) } QVector preRenderingJobs() override { return QVector(); } QVector renderBinJobs() override { return QVector(); } Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr rayCastingJob() override { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr syncLoadingJobs() override { return Qt3DCore::QAspectJobPtr(); } Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override { return Qt3DCore::QAspectJobPtr(); } - void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root); } + void setSceneRoot(Qt3DRender::Render::Entity *root) override { Q_UNUSED(root) } Qt3DRender::Render::Entity *sceneRoot() const override { return nullptr; } Qt3DRender::Render::FrameGraphNode *frameGraphRoot() const override { return nullptr; } Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override { return nullptr; } - void registerEventFilter(Qt3DCore::QEventFilterService *service) override { Q_UNUSED(service); } - void setSettings(Qt3DRender::Render::RenderSettings *settings) override { Q_UNUSED(settings); } + void registerEventFilter(Qt3DCore::QEventFilterService *service) override { Q_UNUSED(service) } + void setSettings(Qt3DRender::Render::RenderSettings *settings) override { Q_UNUSED(settings) } Qt3DRender::Render::RenderSettings *settings() const override { return nullptr; } void markDirty(Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet changes, Qt3DRender::Render::BackendNode *node) override; diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 180ff7ac1..908426570 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -137,7 +137,6 @@ qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) { renderviews \ renderqueue \ renderviewbuilder \ - sendrendercapturejob \ gltexture qtConfig(qt3d-extras) { diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index a343d6e57..ede95fe14 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -77,16 +77,6 @@ private Q_SLOTS: 1 + // PickBoundingVolumeJob 1); // RayCastingJob - // WHEN - renderer.addRenderCaptureSendRequest(Qt3DCore::QNodeId::createId()); - jobs = renderer.preRenderingJobs(); - - // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob - 1); // SendRenderCaptureJob - // WHEN renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); jobs = renderer.preRenderingJobs(); diff --git a/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro b/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro deleted file mode 100644 index 6aff0bebd..000000000 --- a/tests/auto/render/sendrendercapturejob/sendrendercapturejob.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_sendrendercapturejob - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_sendrendercapturejob.cpp - -include(../commons/commons.pri) -include(../../core/common/common.pri) diff --git a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp b/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp deleted file mode 100644 index 53a646ccd..000000000 --- a/tests/auto/render/sendrendercapturejob/tst_sendrendercapturejob.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include "Qt3DRender/QRenderAspect" -#include "Qt3DRender/private/renderer_p.h" -#include "Qt3DRender/private/nodemanagers_p.h" -#include "Qt3DRender/private/rendercapture_p.h" -#include -#include "testpostmanarbiter.h" - -class tst_SendRenderCaptureJob : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void testSendRenderCaptureRequest() - { - // GIVEN - TestArbiter arbiter; - Qt3DRender::Render::RenderCapture *renderCapture = new Qt3DRender::Render::RenderCapture; - Qt3DCore::QBackendNodePrivate::get(renderCapture)->setArbiter(&arbiter); - - QImage image(10, 10, QImage::Format_ARGB32); - - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::SendRenderCaptureJob job; - - Qt3DRender::Render::NodeManagers nodeManagers; - nodeManagers.frameGraphManager()->appendNode(renderCapture->peerId(), renderCapture); - renderer.setNodeManagers(&nodeManagers); - job.setManagers(&nodeManagers); - - renderCapture->requestCapture({ 42, QRect() }); - auto request = renderCapture->takeCaptureRequest(); - renderCapture->addRenderCapture(request.captureId, image); - renderer.addRenderCaptureSendRequest(renderCapture->peerId()); - job.setPendingCaptureRequests(renderer.takePendingRenderCaptureSendRequests()); - - //WHEN - job.run(); - - //THEN - QCOMPARE(arbiter.events.count(), 1); - Qt3DCore::QPropertyUpdatedChangePtr change = arbiter.events.first().staticCast(); - QCOMPARE(change->subjectId(), renderCapture->peerId()); - QCOMPARE(change->propertyName(), "renderCaptureData"); - auto data = change->value().value(); - QCOMPARE(data.data()->captureId, 42); - QCOMPARE(data.data()->image.width(), 10); - QCOMPARE(data.data()->image.height(), 10); - QCOMPARE(data.data()->image.format(), QImage::Format_ARGB32); - - // renderCapture will be deallocated by the nodeManagers destructor - renderer.shutdown(); - } -}; - -QTEST_APPLESS_MAIN(tst_SendRenderCaptureJob) - -#include "tst_sendrendercapturejob.moc" diff --git a/tests/manual/rendercapture-qml/main.qml b/tests/manual/rendercapture-qml/main.qml index 9aff1fefe..98b24e251 100644 --- a/tests/manual/rendercapture-qml/main.qml +++ b/tests/manual/rendercapture-qml/main.qml @@ -50,7 +50,7 @@ import QtQuick 2.2 import QtQuick.Layouts 1.3 -import QtQuick.Controls 1.4 +import QtQuick.Controls 2.12 import Qt3D.Render 2.9 import QtQuick.Scene3D 2.0 -- cgit v1.2.3 From 94e79666cc987fcc928d43f7f82b8c7b9d4c4acc Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Sat, 7 Dec 2019 20:37:43 +0000 Subject: Update textures and disables in postJobs Work was done in postFrame() in main thread anyway, so reduce amount of jobs slightly Change-Id: I8bbb3efcaf9246eb8df1033bde133bc16233f889 Reviewed-by: Paul Lemire --- .../render/computecommand/tst_computecommand.cpp | 8 +------- tests/auto/render/renderer/tst_renderer.cpp | 23 ---------------------- 2 files changed, 1 insertion(+), 30 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp index 2046ecc76..4dc6b4436 100644 --- a/tests/auto/render/computecommand/tst_computecommand.cpp +++ b/tests/auto/render/computecommand/tst_computecommand.cpp @@ -54,11 +54,6 @@ public: ~tst_Renderer() { shutdown(); } - - Qt3DRender::Render::SynchronizerPostFramePtr sendDisablesToFrontendJob() const - { - return m_sendDisablesToFrontendJob; - } }; @@ -337,8 +332,7 @@ private Q_SLOTS: QCOMPARE(computeCommand.isEnabled(), true); // WHEN - auto sendDisablesJob = renderer.sendDisablesToFrontendJob(); - Qt3DCore::QAspectJobPrivate::get(sendDisablesJob.data())->postFrame(&manager); + renderer.jobsDone(&manager); // so Renderer::sendDisablesToFrontend gets called // THEN QCOMPARE(computeCommand.isEnabled(), false); diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp index ede95fe14..0cbc1aefc 100644 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ b/tests/auto/render/renderer/tst_renderer.cpp @@ -100,20 +100,6 @@ private Q_SLOTS: 1); // SendSetFenceHandlesJob // Note: pending set fence handles are only cleared when the job is run - // WHEN - renderer.m_updatedTextureProperties.push_back({{}, {}}); - jobs = renderer.preRenderingJobs(); - - // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob - 1 + // SendBufferCaptureJob - 1 + // SendSetFenceHandlesJob - 1); // SendTextureChangesToFrontend - - // Note: pending texture changes are only cleared when the job is run - // Properly shutdown command thread renderer.shutdown(); } @@ -182,7 +168,6 @@ private Q_SLOTS: 1 + // SyncLoadingJobs 1 + // updateLevelOfDetailJob 1 + // cleanupJob - 1 + // sendDisablesToFrontend 1 + // VAOGatherer 1 + // BufferGathererJob 1 + // TexturesGathererJob @@ -212,7 +197,6 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs - 1 + // sendDisablesToFrontend singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + @@ -233,7 +217,6 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs - 1 + // sendDisablesToFrontend singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount + @@ -253,7 +236,6 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs - 1 + // sendDisablesToFrontend 1 + // EntityEnabledDirty singleRenderViewJobCount + layerCacheJobCount); @@ -275,7 +257,6 @@ private Q_SLOTS: 1 + // UpdateShaderDataTransform 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs - 1 + // sendDisablesToFrontend 1 + // ExpandBoundingVolumeJob singleRenderViewJobCount); @@ -293,7 +274,6 @@ private Q_SLOTS: 1 + // VAOGatherer 1 + // updateSkinningPaletteJob 1 + // SyncLoadingJobs - 1 + // sendDisablesToFrontend singleRenderViewJobCount + singleRenderViewCommandRebuildJobCount + renderViewBuilderMaterialCacheJobCount); @@ -317,7 +297,6 @@ private Q_SLOTS: 1 + // ExpandBoundingVolumeJob 1 + // RenderableEntityFilterPtr 1 + // SyncRenderableEntities - 1 + // sendDisablesToFrontend singleRenderViewCommandRebuildJobCount + singleRenderViewJobCount); @@ -338,7 +317,6 @@ private Q_SLOTS: 1 + // CalculateBoundingVolumeJob 1 + // UpdateMeshTriangleListJob 1 + // BufferGathererJob - 1 + // sendDisablesToFrontend singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); @@ -356,7 +334,6 @@ private Q_SLOTS: 1 + // TexturesGathererJob 1 + // updateSkinningPaletteJob 1 + // SyncTexturesGathererJob - 1 + // sendDisablesToFrontend singleRenderViewJobCount); renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); -- cgit v1.2.3 From b8b516ff1273ebabf64391aa12de45c47326d98b Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 5 Dec 2019 17:23:18 +0000 Subject: Move AspectCommandDebugger to system service, activate command executer - Always compile in AspectCommandDebugger and CommandExecuter - AspectCommandDebugger start when QT3D_COMMAND_SERVER_ENABLED is set - System information service becomes entry point for commands from the debugger - Added commands to enable and disable tracing Change-Id: Ic0d7fe72fa8a118a43ca348ca4284595a71827a4 Reviewed-by: Paul Lemire --- tests/auto/core/core.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro index 001b947d5..13f4a0dc7 100644 --- a/tests/auto/core/core.pro +++ b/tests/auto/core/core.pro @@ -25,10 +25,10 @@ qtConfig(private_tests) { threadpooler \ qpostman \ vector4d_base \ - vector3d_base + vector3d_base \ + aspectcommanddebugger QT_FOR_CONFIG += 3dcore-private - qtConfig(qt3d-profile-jobs): SUBDIRS += aspectcommanddebugger qtConfig(qt3d-simd-sse2) { SUBDIRS += \ vector4d_sse \ -- cgit v1.2.3 From b7873ef58825993f7b820ec78842d0e5bbd7a8a5 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 7 Nov 2019 08:26:57 +0100 Subject: QSortPolicy: add Uniform sorting mode We used to perform uniform minization between adjacent render commands all the time. Since this can yield to a higher CPU usages (but more efficient rendering submission), we now make this step optional. [ChangeLog] QSortPolicy add Uniform mode (to control whether uniform minization should be performed) Change-Id: I5c0e0dba22400a9884ee1d75426fd76b073fdcb5 Reviewed-by: Sean Harmer --- tests/auto/render/renderviews/tst_renderviews.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index 1558b68c9..086ff0220 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -253,6 +253,7 @@ private Q_SLOTS: // WHEN renderView.setCommands(rawCommands); + renderView.addSortType((QVector() << QSortPolicy::Uniform)); renderView.sort(); // THEN -- cgit v1.2.3 From a40654ad451569a19b49bd2d6b9cfc4fa0cc12b8 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Sun, 12 Jan 2020 09:23:20 +0000 Subject: Remove use of messages for RayCaster Change-Id: Ibe0b38df62700608135788331adfcb7fa28159a7 Reviewed-by: Paul Lemire --- tests/auto/render/qraycaster/tst_qraycaster.cpp | 55 ++++++------------------- 1 file changed, 13 insertions(+), 42 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/qraycaster/tst_qraycaster.cpp b/tests/auto/render/qraycaster/tst_qraycaster.cpp index 720c372de..8ac084545 100644 --- a/tests/auto/render/qraycaster/tst_qraycaster.cpp +++ b/tests/auto/render/qraycaster/tst_qraycaster.cpp @@ -80,7 +80,7 @@ private Q_SLOTS: QScopedPointer rayCaster(new Qt3DRender::QRayCaster()); QVERIFY(!rayCaster->isEnabled()); - QVERIFY(rayCaster->direction().length() > 0.); + QVERIFY(rayCaster->direction().length() > 0.f); QCOMPARE(rayCaster->runMode(), Qt3DRender::QAbstractRayCaster::SingleShot); // WHEN @@ -125,13 +125,11 @@ private Q_SLOTS: QCoreApplication::processEvents(); // THEN - QCOMPARE(arbiter.events.size(), 1); - auto addChange = arbiter.events.first().staticCast(); - QCOMPARE(addChange->propertyName(), "layer"); - QCOMPARE(addChange->subjectId(), rayCaster->id()); - QCOMPARE(addChange->addedNodeId(), rayCaster->layers().at(0)->id()); - QCOMPARE(addChange->type(), Qt3DCore::PropertyValueAdded); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data()); + arbiter.dirtyNodes.clear(); arbiter.events.clear(); // WHEN @@ -141,13 +139,11 @@ private Q_SLOTS: QCoreApplication::processEvents(); // THEN - QCOMPARE(arbiter.events.size(), 1); - addChange = arbiter.events.first().staticCast(); - QCOMPARE(addChange->propertyName(), "layer"); - QCOMPARE(addChange->subjectId(), rayCaster->id()); - QCOMPARE(addChange->addedNodeId(), rayCaster->layers().at(1)->id()); - QCOMPARE(addChange->type(), Qt3DCore::PropertyValueAdded); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data()); + arbiter.dirtyNodes.clear(); arbiter.events.clear(); // WHEN @@ -156,13 +152,11 @@ private Q_SLOTS: QCoreApplication::processEvents(); // THEN - QCOMPARE(arbiter.events.size(), 1); - auto removeChange = arbiter.events.first().staticCast(); - QCOMPARE(removeChange->propertyName(), "layer"); - QCOMPARE(removeChange->subjectId(), rayCaster->id()); - QCOMPARE(removeChange->removedNodeId(), layer->id()); - QCOMPARE(removeChange->type(), Qt3DCore::PropertyValueRemoved); + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), rayCaster.data()); + arbiter.dirtyNodes.clear(); arbiter.events.clear(); } @@ -209,29 +203,6 @@ private Q_SLOTS: << QByteArray(SIGNAL(hitsChanged(const Hits &))) << QByteArrayLiteral("hits"); } - - void checkBackendUpdates() - { - // GIVEN - QFETCH(QByteArray, signalPrototype); - QFETCH(QByteArray, propertyName); - QScopedPointer rayCaster(new MyRayCaster()); - QSignalSpy spy(rayCaster.data(), signalPrototype.constData()); - Qt3DRender::QRayCaster::Hits hits; - - // WHEN - // Create Backend Change and distribute it to frontend node - Qt3DCore::QPropertyUpdatedChangePtr e(new Qt3DCore::QPropertyUpdatedChange(rayCaster->id())); - e->setPropertyName(propertyName.constData()); - QVariant v; - v.setValue(hits); - e->setValue(v); - rayCaster->sceneChangeEvent(e); - - // THEN - // Check that the QRayCaster triggers the expected signal - QCOMPARE(spy.count(), 1); - } }; QTEST_MAIN(tst_QRayCaster) -- cgit v1.2.3 From 65ed4fa2ff95b54eacd82a7fb91f213464796756 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Tue, 10 Dec 2019 09:38:00 +0000 Subject: Use animation rather than event to drive simulation Using events can be problematic as they contribute to flooding of the event queue leading to issues with running animations. So we now use an actual animation which runs in a loop and triggers every 1ms (rendering still vsync locked though). If animation have not been enabled for the qt build, we fall back to using events as before. Tests were changes since frame progress is no longer driven by events, so processEvents does not trigger a frame update. Change-Id: I89b11862ef432dffae0c3dfb140eedd61754697e Reviewed-by: Paul Lemire --- tests/auto/core/nodes/tst_nodes.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests') diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index b5291cab7..43d9f7778 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -944,6 +944,7 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent() // GIVEN ObserverSpy spy; Qt3DCore::QAspectEngine engine; + engine.setRunMode(Qt3DCore::QAspectEngine::Manual); QScopedPointer root(new MyQEntity()); root->setArbiterAndEngine(&spy, &engine); auto aspect = new TestAspect; @@ -953,6 +954,7 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent() MyQNode *child2(new MyQNode(root.data())); QCoreApplication::processEvents(); + engine.processFrame(); // Due to the way we create root, it has a backend QVERIFY(Qt3DCore::QNodePrivate::get(root.data())->m_hasBackendNode == true); @@ -983,6 +985,7 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent() // WHEN QCoreApplication::processEvents(); + engine.processFrame(); // THEN QCOMPARE(spy.events.size(), 2); @@ -1059,6 +1062,7 @@ void tst_Nodes::checkParentChangeFromExistingBackendParentToNewlyCreatedParent() // WHEN QCoreApplication::processEvents(); + engine.processFrame(); // THEN QCOMPARE(spy.events.size(), 2); @@ -1237,6 +1241,7 @@ void tst_Nodes::checkAllBackendCreationDoneInSingleFrame() // GIVEN ObserverSpy spy; Qt3DCore::QAspectEngine engine; + engine.setRunMode(Qt3DCore::QAspectEngine::Manual); auto aspect = new TestAspect; engine.registerAspect(aspect); @@ -1269,6 +1274,7 @@ void tst_Nodes::checkAllBackendCreationDoneInSingleFrame() // WHEN QCoreApplication::processEvents(); + engine.processFrame(); // THEN - both children have their backend nodes actually created. QCOMPARE(aspect->events.count(), 2); -- cgit v1.2.3 From df5a63b059956e8a717db9110327cc86612cc934 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 9 Jan 2020 11:36:39 +0000 Subject: Fix usage of C++14 features Change-Id: Ibd460eceafdd29d7d88ac2418496dc7002de1095 Reviewed-by: Paul Lemire --- .../global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tests') diff --git a/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp b/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp index 9eec010be..00e4890c8 100644 --- a/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp +++ b/tests/auto/global/aspects_startup_shutdown/tst_aspects_startup_shutdown.cpp @@ -143,6 +143,8 @@ private slots: void checkStartupAndShutdownImmediately() { + QSKIP("Fails on CI for some unexplained reason"); + // GIVEN QWindow *win = new QWindow(); win->setSurfaceType(QSurface::OpenGLSurface); @@ -170,6 +172,8 @@ private slots: void checkStartupAndShutdownAfterAFewFrames() { + QSKIP("Fails on CI for some unexplained reason"); + // GIVEN QWindow *win = new QWindow(); win->setSurfaceType(QSurface::OpenGLSurface); -- cgit v1.2.3 From 0dc38ecbbff992701756d92821e20f360821710f Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Sat, 11 Jan 2020 11:17:55 +0000 Subject: Fix deprecation handling Change-Id: If981333f7a3d78028d4f08c59867453d4192b955 Task-number: QTBUG-81058 Reviewed-by: Paul Lemire --- .../animationutils/tst_animationutils.cpp | 2 - tests/auto/core/common/qbackendnodetester.cpp | 9 + tests/auto/core/common/testpostmanarbiter.cpp | 4 + tests/auto/core/common/testpostmanarbiter.h | 3 + tests/auto/core/nodes/tst_nodes.cpp | 4 + .../core/qchangearbiter/tst_qchangearbiter.cpp | 4 + tests/auto/core/qentity/tst_qentity.cpp | 4 + tests/auto/core/qpostman/tst_qpostman.cpp | 221 --------------------- tests/auto/core/qscene/tst_qscene.cpp | 4 + tests/auto/core/qtransform/tst_qtransform.cpp | 4 + tests/auto/coretest/qbackendnodetester.cpp | 6 + tests/auto/coretest/testpostmanarbiter.cpp | 4 + tests/auto/render/entity/tst_entity.cpp | 4 + .../qabstracttexture/tst_qabstracttexture.cpp | 3 + tests/auto/render/qgeometry/tst_qgeometry.cpp | 4 + .../render/qrendercapture/tst_qrendercapture.cpp | 3 + tests/auto/render/qsetfence/tst_qsetfence.cpp | 6 +- .../render/qshaderprogram/tst_qshaderprogram.cpp | 3 + tests/auto/render/setfence/tst_setfence.cpp | 4 +- 19 files changed, 70 insertions(+), 226 deletions(-) (limited to 'tests') diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 463656557..05558192d 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -57,7 +56,6 @@ Q_DECLARE_METATYPE(Clock *) Q_DECLARE_METATYPE(ChannelMapper *) Q_DECLARE_METATYPE(AnimationClip *) Q_DECLARE_METATYPE(QVector) -Q_DECLARE_METATYPE(QVector) Q_DECLARE_METATYPE(Channel) Q_DECLARE_METATYPE(AnimatorEvaluationData) Q_DECLARE_METATYPE(ClipEvaluationData) diff --git a/tests/auto/core/common/qbackendnodetester.cpp b/tests/auto/core/common/qbackendnodetester.cpp index a2685f556..13f4683d9 100644 --- a/tests/auto/core/common/qbackendnodetester.cpp +++ b/tests/auto/core/common/qbackendnodetester.cpp @@ -56,20 +56,29 @@ void QBackendNodeTester::simulateInitialization(QNode *frontend, QBackendNode *b { Q_ASSERT(frontend); Q_ASSERT(backend); + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED const auto change = frontend->createNodeCreationChange(); backend->setPeerId(change->subjectId()); backend->setEnabled(change->isNodeEnabled()); backend->initializeFromPeer(change); + QT_WARNING_POP } void QBackendNodeTester::sceneChangeEvent(QBackendNode *backend, const Qt3DCore::QSceneChangePtr &e) { + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED backend->sceneChangeEvent(e); + QT_WARNING_POP } QNodeCreatedChangeBasePtr QBackendNodeTester::creationChange(QNode *frontend) const { + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED return frontend->createNodeCreationChange(); + QT_WARNING_POP } } // namespace Qt3DCore diff --git a/tests/auto/core/common/testpostmanarbiter.cpp b/tests/auto/core/common/testpostmanarbiter.cpp index 5869cbad3..f0c362744 100644 --- a/tests/auto/core/common/testpostmanarbiter.cpp +++ b/tests/auto/core/common/testpostmanarbiter.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include "testpostmanarbiter.h" #include diff --git a/tests/auto/core/common/testpostmanarbiter.h b/tests/auto/core/common/testpostmanarbiter.h index cecc24f93..e927c2489 100644 --- a/tests/auto/core/common/testpostmanarbiter.h +++ b/tests/auto/core/common/testpostmanarbiter.h @@ -70,7 +70,10 @@ public: void setArbiterOnNode(Qt3DCore::QNode *node); void addDirtyFrontEndNode(Qt3DCore::QNode *node) final; + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED void addDirtyFrontEndNode(Qt3DCore::QNode *node, Qt3DCore::QNode *subNode, const char *property, Qt3DCore::ChangeFlag change) final; + QT_WARNING_POP void removeDirtyFrontEndNode(Qt3DCore::QNode *node) final; private: diff --git a/tests/auto/core/nodes/tst_nodes.cpp b/tests/auto/core/nodes/tst_nodes.cpp index 87f66bab2..2e74acd61 100644 --- a/tests/auto/core/nodes/tst_nodes.cpp +++ b/tests/auto/core/nodes/tst_nodes.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp index e54193398..3e9b24408 100644 --- a/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp +++ b/tests/auto/core/qchangearbiter/tst_qchangearbiter.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/core/qentity/tst_qentity.cpp b/tests/auto/core/qentity/tst_qentity.cpp index 7770a2632..7b41c9783 100644 --- a/tests/auto/core/qentity/tst_qentity.cpp +++ b/tests/auto/core/qentity/tst_qentity.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/core/qpostman/tst_qpostman.cpp b/tests/auto/core/qpostman/tst_qpostman.cpp index f548d38fa..d0dfa0f49 100644 --- a/tests/auto/core/qpostman/tst_qpostman.cpp +++ b/tests/auto/core/qpostman/tst_qpostman.cpp @@ -86,227 +86,6 @@ private Q_SLOTS: QCOMPARE(QPostmanPrivate::get(&postman)->m_scene, &scene); } - void checkSceneChangeEvent() - { - // GIVEN - QScopedPointer scene(new QScene); - QPostman postman; - TestArbiter arbiter; - QNode rootNode; - NodeChangeReceiver *receiverNode = new NodeChangeReceiver(); - - QNodePrivate::get(&rootNode)->m_scene = scene.data(); - scene->setArbiter(&arbiter); - postman.setScene(scene.data()); - // Setting the parent (which has a scene) adds the node into the observable lookup - // table of the scene which is needed by the postman to distribute changes - static_cast(receiverNode)->setParent(&rootNode); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(receiverNode->hasReceivedChange(), false); - QCOMPARE(QNodePrivate::get(receiverNode)->m_scene, scene.data()); - - // WHEN - QPropertyUpdatedChangePtr updateChange(new QPropertyUpdatedChange(receiverNode->id())); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - postman.sceneChangeEvent(updateChange); - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(receiverNode->hasReceivedChange(), true); - } - - void checkNotifyBackend() - { - // GIVEN - QScopedPointer scene(new QScene); - QPostman postman; - TestArbiter arbiter; - - scene->setArbiter(&arbiter); - postman.setScene(scene.data()); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - - // WHEN - QPropertyUpdatedChangePtr updateChange(new QPropertyUpdatedChange(QNodeId())); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - postman.notifyBackend(updateChange); - - QCoreApplication::processEvents(); - - // THEN - QCOMPARE(arbiter.events.size(), 1); - } - - void checkShouldNotifyFrontend() - { - // GIVEN - QScopedPointer scene(new QScene); - QPostman postman; - TestArbiter arbiter; - QNode rootNode; - NodeChangeReceiver *receiverNode = new NodeChangeReceiver(); - - QNodePrivate::get(&rootNode)->m_scene = scene.data(); - scene->setArbiter(&arbiter); - postman.setScene(scene.data()); - // Setting the parent (which has a scene) adds the node into the observable lookup - // table of the scene which is needed by the postman to distribute changes - static_cast(receiverNode)->setParent(&rootNode); - QCoreApplication::processEvents(); - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - - - // THEN -> we do track properties by default QNode::DefaultTrackMode - // (unless marked as an intermediate change) - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - - { - // WHEN - receiverNode->setDefaultPropertyTrackingMode(QNode::TrackAllValues); - - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate - = true; - - // THEN -> we do track properties marked as intermediate when - // using TrackAllPropertiesMode - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - - { - // GIVEN - receiverNode->setDefaultPropertyTrackingMode(QNode::DontTrackValues); - receiverNode->setPropertyTracking(QStringLiteral("vette"), Qt3DCore::QNode::TrackAllValues); - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate - = true; - - // THEN -> we don't track properties by default, unless named when - // using TrackNamedPropertiesMode - QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); - } - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("vette"); - QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate - = true; - - // THEN - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - } - - { - // GIVEN - receiverNode->setPropertyTracking(QStringLiteral("vette"), Qt3DCore::QNode::TrackAllValues); - receiverNode->setDefaultPropertyTrackingMode(QNode::TrackAllValues); - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - - // THEN -> we don't track properties by default - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("vette"); - - // THEN -> we don't track properties by default - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - } - - { - // GIVEN - receiverNode->clearPropertyTrackings(); - receiverNode->setDefaultPropertyTrackingMode(QNode::TrackFinalValues); - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - - // THEN -> we do track properties by default, unless marked as intermediate - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - - { - // WHEN - auto addedChange - = QPropertyNodeAddedChangePtr::create(receiverNode->id(), receiverNode); - - // THEN -> only QPropertyUpdatedChangePtr are filtered - QCOMPARE(postman.shouldNotifyFrontend(addedChange), true); - } - { - // WHEN - auto removedChange - = QPropertyNodeRemovedChangePtr::create(receiverNode->id(), receiverNode); - - // THEN -> only QPropertyUpdatedChangePtr are filtered - QCOMPARE(postman.shouldNotifyFrontend(removedChange), true); - } - } - - { - // GIVEN - receiverNode->clearPropertyTrackings(); - receiverNode->setDefaultPropertyTrackingMode(QNode::TrackFinalValues); - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - QPropertyUpdatedChangeBasePrivate::get(updateChange.data())->m_isIntermediate - = true; - - // THEN -> we don't track intermediate properties by default - QCOMPARE(postman.shouldNotifyFrontend(updateChange), false); - } - - { - // WHEN - auto updateChange = QPropertyUpdatedChangePtr::create(receiverNode->id()); - updateChange->setValue(1584); - updateChange->setPropertyName("someName"); - - // THEN - QCOMPARE(postman.shouldNotifyFrontend(updateChange), true); - } - - } - } - }; QTEST_MAIN(tst_QPostman) diff --git a/tests/auto/core/qscene/tst_qscene.cpp b/tests/auto/core/qscene/tst_qscene.cpp index ecc72e992..eb6a8c5ec 100644 --- a/tests/auto/core/qscene/tst_qscene.cpp +++ b/tests/auto/core/qscene/tst_qscene.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/core/qtransform/tst_qtransform.cpp b/tests/auto/core/qtransform/tst_qtransform.cpp index 37848ffd6..18a906e4c 100644 --- a/tests/auto/core/qtransform/tst_qtransform.cpp +++ b/tests/auto/core/qtransform/tst_qtransform.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/coretest/qbackendnodetester.cpp b/tests/auto/coretest/qbackendnodetester.cpp index be9767828..bd5fb85d1 100644 --- a/tests/auto/coretest/qbackendnodetester.cpp +++ b/tests/auto/coretest/qbackendnodetester.cpp @@ -57,15 +57,21 @@ void QBackendNodeTester::simulateInitialization(QNode *frontend, QBackendNode *b { Q_ASSERT(frontend); Q_ASSERT(backend); + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED const auto change = frontend->createNodeCreationChange(); backend->setPeerId(change->subjectId()); backend->setEnabled(change->isNodeEnabled()); backend->initializeFromPeer(change); + QT_WARNING_POP } void QBackendNodeTester::sceneChangeEvent(QBackendNode *backend, const Qt3DCore::QSceneChangePtr &e) { + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED backend->sceneChangeEvent(e); + QT_WARNING_POP } } // namespace Qt3DCore diff --git a/tests/auto/coretest/testpostmanarbiter.cpp b/tests/auto/coretest/testpostmanarbiter.cpp index d1263b8f7..d2e404809 100644 --- a/tests/auto/coretest/testpostmanarbiter.cpp +++ b/tests/auto/coretest/testpostmanarbiter.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include "testpostmanarbiter_p.h" #include diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index 93f2614b8..2629e6953 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp b/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp index a1973176e..6fad09a0d 100644 --- a/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp +++ b/tests/auto/render/qabstracttexture/tst_qabstracttexture.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/qgeometry/tst_qgeometry.cpp b/tests/auto/render/qgeometry/tst_qgeometry.cpp index 017314ecf..e790ba9cc 100644 --- a/tests/auto/render/qgeometry/tst_qgeometry.cpp +++ b/tests/auto/render/qgeometry/tst_qgeometry.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp index 9ed7651fc..35c645d41 100644 --- a/tests/auto/render/qrendercapture/tst_qrendercapture.cpp +++ b/tests/auto/render/qrendercapture/tst_qrendercapture.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/qsetfence/tst_qsetfence.cpp b/tests/auto/render/qsetfence/tst_qsetfence.cpp index c602e6f5c..ad92e9fe0 100644 --- a/tests/auto/render/qsetfence/tst_qsetfence.cpp +++ b/tests/auto/render/qsetfence/tst_qsetfence.cpp @@ -37,6 +37,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include @@ -153,7 +157,6 @@ private Q_SLOTS: QCOMPARE(creationChanges.size(), 1); const auto creationChangeData = qSharedPointerCast>(creationChanges.first()); - const Qt3DRender::QSetFenceData cloneData = creationChangeData->data; QCOMPARE(setFence.id(), creationChangeData->subjectId()); QCOMPARE(setFence.isEnabled(), true); @@ -174,7 +177,6 @@ private Q_SLOTS: QCOMPARE(creationChanges.size(), 1); const auto creationChangeData = qSharedPointerCast>(creationChanges.first()); - const Qt3DRender::QSetFenceData cloneData = creationChangeData->data; QCOMPARE(setFence.id(), creationChangeData->subjectId()); QCOMPARE(setFence.isEnabled(), false); diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp index a261d0860..18dd1306a 100644 --- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp +++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/setfence/tst_setfence.cpp b/tests/auto/render/setfence/tst_setfence.cpp index 92f7a0acc..75c414e7f 100644 --- a/tests/auto/render/setfence/tst_setfence.cpp +++ b/tests/auto/render/setfence/tst_setfence.cpp @@ -37,7 +37,9 @@ ** ****************************************************************************/ - +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include -- cgit v1.2.3 From 4cd35e87b63d2ff4bc4ee88b6080f812de45d239 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Fri, 24 Jan 2020 11:08:48 +0000 Subject: Clean up tracing code - Removed some old optional timing code. - Separated jobsDone into 2 parts since, on single threaded rendering mode (ie macOS), the render aspect blocks until the next vsync which confuses tracing Change-Id: Icb641e3f8079da2cb9af0416b0f7c4dc4dd36c3c Reviewed-by: Paul Lemire --- tests/auto/render/commons/testrenderer.h | 1 + 1 file changed, 1 insertion(+) (limited to 'tests') diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 05ef4c130..1241bb0e0 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -43,6 +43,7 @@ public: API api() const override { return AbstractRenderer::OpenGL; } qint64 time() const override { return 0; } void setTime(qint64 time) override { Q_UNUSED(time) } + void setJobsInLastFrame(int jobsInLastFrame) override { Q_UNUSED(jobsInLastFrame) } void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override { m_managers = m; } void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services) } void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed) } -- cgit v1.2.3 From 64f983af68440ff73b985b133a73bd66178557da Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 13 Jan 2020 07:53:41 +0100 Subject: QMouseDevice: add updateAxesContinuously property The default behavior is to only update axes when one of the mouse buttons is pressed. This property, when enabled, allows to record X/Y axes value changes regardless of the state of the mouse buttons. [ChangeLog] QMouseDevice add updateAxesContinuously property Change-Id: Ib54a1e54c6c278ea08722760c2d317ec46437b2f Reviewed-by: Mike Krus --- tests/auto/input/mousedevice/tst_mousedevice.cpp | 73 ++++++++++++++++++++-- tests/auto/input/qmousedevice/tst_qmousedevice.cpp | 45 +++++++++++++ 2 files changed, 114 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/input/mousedevice/tst_mousedevice.cpp b/tests/auto/input/mousedevice/tst_mousedevice.cpp index f245e399d..95ae8de56 100644 --- a/tests/auto/input/mousedevice/tst_mousedevice.cpp +++ b/tests/auto/input/mousedevice/tst_mousedevice.cpp @@ -58,6 +58,7 @@ private Q_SLOTS: QCOMPARE(backendMouseDevice.previousPos(), QPointF()); QCOMPARE(backendMouseDevice.wasPressed(), false); QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); } void checkInitializeFromPeer() @@ -85,6 +86,7 @@ private Q_SLOTS: QCOMPARE(backendMouseDevice.previousPos(), QPointF()); QCOMPARE(backendMouseDevice.wasPressed(), false); QCOMPARE(backendMouseDevice.sensitivity(), 0.8f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); } { // WHEN @@ -125,6 +127,7 @@ private Q_SLOTS: QCOMPARE(backendMouseDevice.previousPos(), QPointF(400.0f, 400.0f)); QCOMPARE(backendMouseDevice.wasPressed(), true); QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); // WHEN eventList = QList() << QT_PREPEND_NAMESPACE(QMouseEvent)(QMouseEvent::MouseMove, @@ -147,12 +150,13 @@ private Q_SLOTS: QCOMPARE(backendMouseDevice.previousPos(), QPointF(600.0f, 600.0f)); QCOMPARE(backendMouseDevice.wasPressed(), true); QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); // WHEN eventList = QList() << QT_PREPEND_NAMESPACE(QMouseEvent)(QMouseEvent::MouseButtonRelease, - QPointF(600.0f, 600.0f), - QPointF(600.0f, 600.0f), - QPointF(600.0f, 600.0f), + QPointF(800.0f, 800.0f), + QPointF(800.0f, 800.0f), + QPointF(800.0f, 800.0f), Qt::LeftButton, Qt::NoButton, Qt::NoModifier); @@ -166,9 +170,61 @@ private Q_SLOTS: QCOMPARE(backendMouseDevice.mouseState().leftPressed, false); QCOMPARE(backendMouseDevice.mouseState().rightPressed, false); QCOMPARE(backendMouseDevice.mouseState().centerPressed, false); - QCOMPARE(backendMouseDevice.previousPos(), QPointF(600.0f, 600.0f)); + QCOMPARE(backendMouseDevice.previousPos(), QPointF(800.0f, 800.0f)); QCOMPARE(backendMouseDevice.wasPressed(), false); QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); + + // WHEN + eventList = QList() << QT_PREPEND_NAMESPACE(QMouseEvent)(QMouseEvent::MouseMove, + QPointF(900.0f, 900.0f), + QPointF(900.0f, 900.0f), + QPointF(900.0f, 900.0f), + Qt::NoButton, + Qt::NoButton, + Qt::NoModifier); + + // THEN -> no axes update + backendMouseDevice.updateMouseEvents(eventList); + QCOMPARE(backendMouseDevice.mouseState().xAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().yAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().wXAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().wYAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().leftPressed, false); + QCOMPARE(backendMouseDevice.mouseState().rightPressed, false); + QCOMPARE(backendMouseDevice.mouseState().centerPressed, false); + QCOMPARE(backendMouseDevice.previousPos(), QPointF(900.0f, 900.0f)); + QCOMPARE(backendMouseDevice.wasPressed(), false); + QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), false); + + + // WHEN + eventList = QList() << QT_PREPEND_NAMESPACE(QMouseEvent)(QMouseEvent::MouseMove, + QPointF(1000.0f, 1000.0f), + QPointF(1000.0f, 1000.0f), + QPointF(1000.0f, 1000.0f), + Qt::NoButton, + Qt::NoButton, + Qt::NoModifier); + + Qt3DInput::QMouseDevice mouseDevice; + mouseDevice.setUpdateAxesContinuously(true); + backendMouseDevice.syncFromFrontEnd(&mouseDevice, false); + backendMouseDevice.updateMouseEvents(eventList); + + // THEN + QCOMPARE(backendMouseDevice.mouseState().xAxis, (1000.0f - 900.0f) * 0.1f); + QCOMPARE(backendMouseDevice.mouseState().yAxis, (900.0f - 1000.0f) * 0.1f); + QCOMPARE(backendMouseDevice.mouseState().wXAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().wYAxis, 0.0f); + QCOMPARE(backendMouseDevice.mouseState().leftPressed,false); + QCOMPARE(backendMouseDevice.mouseState().rightPressed, false); + QCOMPARE(backendMouseDevice.mouseState().centerPressed, false); + QCOMPARE(backendMouseDevice.previousPos(), QPointF(1000.0f, 1000.0f)); + QCOMPARE(backendMouseDevice.wasPressed(), false); + QCOMPARE(backendMouseDevice.sensitivity(), 0.1f); + QCOMPARE(backendMouseDevice.updateAxesContinuously(), true); } void checkMouseWheelState() @@ -241,6 +297,15 @@ private Q_SLOTS: // THEN QCOMPARE(backendMouseDevice.sensitivity(), newValue); } + { + // WHEN + const bool newValue = true; + mouseDevice.setUpdateAxesContinuously(newValue); + backendMouseDevice.syncFromFrontEnd(&mouseDevice, false); + + // THEN + QCOMPARE(backendMouseDevice.updateAxesContinuously(), newValue); + } } }; diff --git a/tests/auto/input/qmousedevice/tst_qmousedevice.cpp b/tests/auto/input/qmousedevice/tst_qmousedevice.cpp index fd2c8e603..6a8f39c71 100644 --- a/tests/auto/input/qmousedevice/tst_qmousedevice.cpp +++ b/tests/auto/input/qmousedevice/tst_qmousedevice.cpp @@ -50,6 +50,7 @@ private Q_SLOTS: // THEN QCOMPARE(mouseDevice.sensitivity(), 0.1f); + QCOMPARE(mouseDevice.updateAxesContinuously(), false); QCOMPARE(mouseDevice.axisCount(), 4); QCOMPARE(mouseDevice.buttonCount(), 3); QCOMPARE(mouseDevice.axisNames(), QStringList() @@ -96,6 +97,25 @@ private Q_SLOTS: QCOMPARE(mouseDevice.sensitivity(), newValue); QCOMPARE(spy.count(), 0); } + { + // WHEN + QSignalSpy spy(&mouseDevice, SIGNAL(updateAxesContinuouslyChanged(bool))); + const bool newValue = true; + mouseDevice.setUpdateAxesContinuously(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mouseDevice.updateAxesContinuously(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mouseDevice.setUpdateAxesContinuously(newValue); + + // THEN + QCOMPARE(mouseDevice.updateAxesContinuously(), newValue); + QCOMPARE(spy.count(), 0); + } } void checkCreationData() @@ -175,6 +195,31 @@ private Q_SLOTS: } + void checkUpdateAxesContinuouslyUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DInput::QMouseDevice mouseDevice; + arbiter.setArbiterOnNode(&mouseDevice); + + { + // WHEN + mouseDevice.setUpdateAxesContinuously(true); + // THEN + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), &mouseDevice); + } + + { + // WHEN + mouseDevice.setSensitivity(true); + + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), &mouseDevice); + } + + } + }; QTEST_MAIN(tst_QMouseDevice) -- cgit v1.2.3 From c5211b7026ebf26bc82889437329ae2cc11e9725 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 27 Jan 2020 14:13:11 +0100 Subject: Unit tests for qscheduler Change-Id: Iaa26160736bc6b92ecf0be767cb289d776cf46ad Reviewed-by: Mike Krus --- tests/auto/core/core.pro | 3 +- tests/auto/core/qscheduler/qscheduler.pro | 7 + tests/auto/core/qscheduler/tst_qscheduler.cpp | 201 ++++++++++++++++++++++++++ 3 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 tests/auto/core/qscheduler/qscheduler.pro create mode 100644 tests/auto/core/qscheduler/tst_qscheduler.cpp (limited to 'tests') diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro index 13f4a0dc7..994c6206c 100644 --- a/tests/auto/core/core.pro +++ b/tests/auto/core/core.pro @@ -26,7 +26,8 @@ qtConfig(private_tests) { qpostman \ vector4d_base \ vector3d_base \ - aspectcommanddebugger + aspectcommanddebugger \ + qscheduler QT_FOR_CONFIG += 3dcore-private qtConfig(qt3d-simd-sse2) { diff --git a/tests/auto/core/qscheduler/qscheduler.pro b/tests/auto/core/qscheduler/qscheduler.pro new file mode 100644 index 000000000..078716116 --- /dev/null +++ b/tests/auto/core/qscheduler/qscheduler.pro @@ -0,0 +1,7 @@ +TARGET = tst_qscheduler +CONFIG += testcase +TEMPLATE = app + +SOURCES += tst_qscheduler.cpp + +QT += testlib 3dcore 3dcore-private diff --git a/tests/auto/core/qscheduler/tst_qscheduler.cpp b/tests/auto/core/qscheduler/tst_qscheduler.cpp new file mode 100644 index 000000000..d1afb5aac --- /dev/null +++ b/tests/auto/core/qscheduler/tst_qscheduler.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include + +using namespace Qt3DCore; + +class JobPrivate : public QAspectJobPrivate +{ + bool m_postFrameCalled = false; + + +public: + // QAspectJobPrivate interface + void postFrame(QAspectManager *aspectManager) + { + Q_ASSERT(aspectManager); + m_postFrameCalled = true; + } + + bool postFrameCalled() const + { + return m_postFrameCalled; + } +}; + +class Job : public QAspectJob +{ + bool m_wasExecuted = false; + +public: + Job() + : QAspectJob(*new JobPrivate) + {} + + bool wasExecuted() const + { + return m_wasExecuted; + } + + bool postFrameCalled() const + { + Q_D(const Job); + return d->postFrameCalled(); + } + + void run() override + { + m_wasExecuted = true; + } + +private: + Q_DECLARE_PRIVATE(Job) +}; +using JobPtr = QSharedPointer; + +class AspectPrivate : public QAbstractAspectPrivate +{ + bool m_jobsDoneCalled = false; + bool m_frameDoneCalled = false; + +public: + + bool jobsDoneCalled() const + { + return m_jobsDoneCalled; + } + + bool frameDoneCalled() const + { + return m_frameDoneCalled; + } + + // QAspectJobProviderInterface interface + void jobsDone() override + { + m_jobsDoneCalled = true; + } + + void frameDone() override + { + m_frameDoneCalled = true; + } +}; + +class Aspect : public QAbstractAspect +{ + Q_OBJECT + +public: + Aspect() + : QAbstractAspect(*new AspectPrivate) + {} + + JobPtr firstJob() const { return m_first; } + JobPtr secondJob() const { return m_second; } + +private: + // QAbstractAspect interface + QVector jobsToExecute(qint64) + { + return { m_first, m_second }; + } + + JobPtr m_first = JobPtr::create(); + JobPtr m_second = JobPtr::create(); + Q_DECLARE_PRIVATE(Aspect) +}; + +class tst_QScheduler : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + QScheduler scheduler; + + // THEN + QVERIFY(scheduler.aspectManager() == nullptr); + + // WHEN + QAspectManager m; + scheduler.setAspectManager(&m); + + // THEN + QCOMPARE(scheduler.aspectManager(), &m); + } + + void checkScheduleAndWaitForFrameAspectJobs() + { + // GIVEN + QScheduler scheduler; + QAspectManager manager; + Aspect aspect; + AspectPrivate *aspectPriv = static_cast(QObjectPrivate::get(&aspect)); + + manager.registerAspect(&aspect); + scheduler.setAspectManager(&manager); + + // THEN + const JobPtr first = aspect.firstJob(); + const JobPtr second = aspect.secondJob(); + QVERIFY(!aspectPriv->jobsDoneCalled()); + QVERIFY(!aspectPriv->frameDoneCalled()); + QVERIFY(!first->wasExecuted()); + QVERIFY(!second->wasExecuted()); + QVERIFY(!first->postFrameCalled()); + QVERIFY(!second->postFrameCalled()); + + // WHEN + const int count = scheduler.scheduleAndWaitForFrameAspectJobs(0); + + // THEN + QCOMPARE(count, 2); + QVERIFY(first->wasExecuted()); + QVERIFY(second->wasExecuted()); + QVERIFY(first->postFrameCalled()); + QVERIFY(second->postFrameCalled()); + QVERIFY(aspectPriv->jobsDoneCalled()); + QVERIFY(!aspectPriv->frameDoneCalled()); + + manager.unregisterAspect(&aspect); + } +}; + +QTEST_MAIN(tst_QScheduler) + +#include "tst_qscheduler.moc" -- cgit v1.2.3 From 3e2b688817d615c1458e1144ad0f0f35555475e8 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Thu, 30 Jan 2020 08:31:42 +0000 Subject: Deprecate functor APIs Deprecate functor based APIs for buffer generators, geometry factories, texture data generators and mesh loaders While these are useful for some of Qt3D's internal mechanisms, they complicate some of the backend operations. Will delete some or make them private in Qt6. Change-Id: I64eaa338e0306647867d2084819ef8591e2c91c0 Reviewed-by: Paul Lemire --- tests/auto/extras/common/geometrytesthelper.h | 3 +++ tests/auto/render/buffer/tst_buffer.cpp | 4 ++++ tests/auto/render/ddstextures/tst_ddstextures.cpp | 4 ++++ tests/auto/render/geometry/tst_geometry.cpp | 4 ++++ tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp | 4 ++++ tests/auto/render/gltexture/tst_gltexture.cpp | 4 ++++ tests/auto/render/ktxtextures/tst_ktxtextures.cpp | 4 ++++ tests/auto/render/meshfunctors/tst_meshfunctors.cpp | 4 ++++ tests/auto/render/picking/tst_picking.cpp | 3 +++ tests/auto/render/qbuffer/tst_qbuffer.cpp | 4 ++++ tests/auto/render/qdefaultmeshes/tst_qdefaultmeshes.cpp | 4 ++++ tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp | 4 ++++ tests/auto/render/qmesh/tst_qmesh.cpp | 3 +++ tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp | 3 +++ tests/auto/render/qtextureimage/tst_qtextureimage.cpp | 3 +++ tests/auto/render/qtextureloader/tst_qtextureloader.cpp | 3 +++ tests/auto/render/textures/tst_textures.cpp | 4 ++++ 17 files changed, 62 insertions(+) (limited to 'tests') diff --git a/tests/auto/extras/common/geometrytesthelper.h b/tests/auto/extras/common/geometrytesthelper.h index 48e674cd9..5b04a078b 100644 --- a/tests/auto/extras/common/geometrytesthelper.h +++ b/tests/auto/extras/common/geometrytesthelper.h @@ -42,9 +42,12 @@ inline void generateGeometry(Qt3DRender::QGeometry &geometry) // Get all unique data generators from the buffers referenced by the attributes QHash dataGenerators; for (const auto attribute : attributes) { + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED const auto dataGenerator = attribute->buffer()->dataGenerator(); if (!dataGenerators.contains(dataGenerator)) dataGenerators.insert(dataGenerator, attribute->buffer()); + QT_WARNING_POP } // Generate data for each buffer diff --git a/tests/auto/render/buffer/tst_buffer.cpp b/tests/auto/render/buffer/tst_buffer.cpp index fa1491914..5c2ae296d 100644 --- a/tests/auto/render/buffer/tst_buffer.cpp +++ b/tests/auto/render/buffer/tst_buffer.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/ddstextures/tst_ddstextures.cpp b/tests/auto/render/ddstextures/tst_ddstextures.cpp index 1f33f20e2..ecdb5d234 100644 --- a/tests/auto/render/ddstextures/tst_ddstextures.cpp +++ b/tests/auto/render/ddstextures/tst_ddstextures.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/geometry/tst_geometry.cpp b/tests/auto/render/geometry/tst_geometry.cpp index 09dbb8eb3..a13f6fa40 100644 --- a/tests/auto/render/geometry/tst_geometry.cpp +++ b/tests/auto/render/geometry/tst_geometry.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp index 0f6af16db..19df24680 100644 --- a/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp +++ b/tests/auto/render/geometryrenderer/tst_geometryrenderer.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/gltexture/tst_gltexture.cpp b/tests/auto/render/gltexture/tst_gltexture.cpp index e971078d0..7d8c679f3 100644 --- a/tests/auto/render/gltexture/tst_gltexture.cpp +++ b/tests/auto/render/gltexture/tst_gltexture.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/ktxtextures/tst_ktxtextures.cpp b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp index 57ccd3652..f57bc86b6 100644 --- a/tests/auto/render/ktxtextures/tst_ktxtextures.cpp +++ b/tests/auto/render/ktxtextures/tst_ktxtextures.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp index 1142d1447..f8110085b 100644 --- a/tests/auto/render/meshfunctors/tst_meshfunctors.cpp +++ b/tests/auto/render/meshfunctors/tst_meshfunctors.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/picking/tst_picking.cpp b/tests/auto/render/picking/tst_picking.cpp index d0e6512d5..b281eb6cb 100644 --- a/tests/auto/render/picking/tst_picking.cpp +++ b/tests/auto/render/picking/tst_picking.cpp @@ -82,8 +82,11 @@ public: Qt3DRender::QBuffer *vertexBuffer = static_cast(positionAttr->buffer()); // Load the geometry + QT_WARNING_PUSH + QT_WARNING_DISABLE_DEPRECATED const QByteArray data = (*vertexBuffer->dataGenerator())(); vertexBuffer->setData(data); + QT_WARNING_POP transform->setTranslation(position); diff --git a/tests/auto/render/qbuffer/tst_qbuffer.cpp b/tests/auto/render/qbuffer/tst_qbuffer.cpp index 94c0a49cb..fd96bf1c2 100644 --- a/tests/auto/render/qbuffer/tst_qbuffer.cpp +++ b/tests/auto/render/qbuffer/tst_qbuffer.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/qdefaultmeshes/tst_qdefaultmeshes.cpp b/tests/auto/render/qdefaultmeshes/tst_qdefaultmeshes.cpp index bbecdd187..8c64a005a 100644 --- a/tests/auto/render/qdefaultmeshes/tst_qdefaultmeshes.cpp +++ b/tests/auto/render/qdefaultmeshes/tst_qdefaultmeshes.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include diff --git a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp index 28574d3c5..8cfbc0d23 100644 --- a/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp +++ b/tests/auto/render/qgeometryrenderer/tst_qgeometryrenderer.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include diff --git a/tests/auto/render/qmesh/tst_qmesh.cpp b/tests/auto/render/qmesh/tst_qmesh.cpp index 0df96dd24..d77005dfa 100644 --- a/tests/auto/render/qmesh/tst_qmesh.cpp +++ b/tests/auto/render/qmesh/tst_qmesh.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp b/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp index 4011eeea6..3187dbd52 100644 --- a/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp +++ b/tests/auto/render/qsharedgltexture/tst_qsharedgltexture.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/qtextureimage/tst_qtextureimage.cpp b/tests/auto/render/qtextureimage/tst_qtextureimage.cpp index 4996c877d..ba5c2c3d8 100644 --- a/tests/auto/render/qtextureimage/tst_qtextureimage.cpp +++ b/tests/auto/render/qtextureimage/tst_qtextureimage.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp index dd92894da..b6d949c83 100644 --- a/tests/auto/render/qtextureloader/tst_qtextureloader.cpp +++ b/tests/auto/render/qtextureloader/tst_qtextureloader.cpp @@ -26,6 +26,9 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED #include #include diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp index 555bd09a3..934cc8151 100644 --- a/tests/auto/render/textures/tst_textures.cpp +++ b/tests/auto/render/textures/tst_textures.cpp @@ -26,6 +26,10 @@ ** ****************************************************************************/ +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + #include #include #include -- cgit v1.2.3 From 32755ab5cca668c82b43bbe8b2e907e4f7dd7720 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 31 Jan 2020 09:33:36 +0100 Subject: Fix stale Entity caches Make sure we mark the internal state as dirty when Entities get cleaned up. We could otherwise end up with stale caches referencing Entity's that have been cleaned up (referencing null bounding volumes ...) Change-Id: Ia2d2c67f8635e28690f33c0a7d4c9ff1de0eb471 Reviewed-by: Mike Krus --- tests/auto/render/entity/tst_entity.cpp | 47 +++++++++++++++++++++++-------- tests/auto/render/scene2d/tst_scene2d.cpp | 2 +- 2 files changed, 37 insertions(+), 12 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/entity/tst_entity.cpp b/tests/auto/render/entity/tst_entity.cpp index e3b8e756e..2eeca2b39 100644 --- a/tests/auto/render/entity/tst_entity.cpp +++ b/tests/auto/render/entity/tst_entity.cpp @@ -123,10 +123,12 @@ private slots: TestRenderer renderer; NodeManagers nodeManagers; Qt3DRender::Render::Entity entity; - Qt3DCore::QEntity dummyFrontendEntity; entity.setRenderer(&renderer); entity.setNodeManagers(&nodeManagers); + // THEN + QCOMPARE(renderer.dirtyBits(), 0); + // THEN QVERIFY(entity.componentUuid().isNull()); QVERIFY(entity.componentUuid().isNull()); @@ -141,20 +143,16 @@ private slots: QVERIFY(!entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); QVERIFY(entity.layerIds().isEmpty()); + QCOMPARE(entity.renderer(), &renderer); + + QCOMPARE(renderer.dirtyBits(), 0); // WHEN for (QComponent *component : components) EntityPrivate::get(&entity)->componentAdded(component); - Qt3DCore::QEntity dummyFrontendEntityChild; - // Create nodes in the backend manager - nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntity.id()); - nodeManagers.renderNodesManager()->getOrCreateResource(dummyFrontendEntityChild.id()); - -// TODOSYNC clean up -// // Send children added event to entity -// const auto addEntityChange = QPropertyNodeAddedChangePtr::create(dummyFrontendEntity.id(), &dummyFrontendEntityChild); -// entity.sceneChangeEvent(addEntityChange); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); // THEN QVERIFY(!entity.componentUuid().isNull()); @@ -170,7 +168,7 @@ private slots: QVERIFY(entity.isBoundingVolumeDirty()); QVERIFY(entity.childrenHandles().isEmpty()); QVERIFY(!entity.layerIds().isEmpty()); - QVERIFY(renderer.dirtyBits() != 0); + QCOMPARE(renderer.dirtyBits(), 0); bool containsAll = entity.containsComponentsOfType(); QVERIFY(containsAll); @@ -195,6 +193,9 @@ private slots: containsAll = entity.containsComponentsOfType(); QVERIFY(!containsAll); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); } void checkEntityReparenting() @@ -217,6 +218,9 @@ private slots: QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN auto sendParentChange = [&nodeManagers](const Qt3DCore::QEntity &entity) { Entity *backendEntity = nodeManagers.renderNodesManager()->getOrCreateResource(entity.id()); @@ -238,6 +242,9 @@ private slots: QCOMPARE(backendB->childrenHandles().count(), 1); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN - reparent C to A frontendEntityC.setParent(&frontendEntityA); sendParentChange(frontendEntityC); @@ -251,6 +258,9 @@ private slots: QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN - reparent B to null. frontendEntityB.setParent(static_cast(nullptr)); sendParentChange(frontendEntityB); @@ -264,6 +274,9 @@ private slots: QVERIFY(!backendA->childrenHandles().contains(backendB->handle())); QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); } void checkEntityCleanup() @@ -298,6 +311,9 @@ private slots: QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN - cleaning up a child backendC->cleanup(); @@ -312,6 +328,9 @@ private slots: QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN (cleaning up parent) backendA->cleanup(); @@ -324,6 +343,9 @@ private slots: QVERIFY(backendB->childrenHandles().isEmpty()); QVERIFY(backendC->childrenHandles().isEmpty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); + // WHEN backendB->cleanup(); @@ -335,6 +357,9 @@ private slots: QVERIFY(backendA->parent() == nullptr); QVERIFY(backendB->parent() == nullptr); QVERIFY(backendC->parent() == nullptr); + + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.resetDirty(); } void shouldHandleSingleComponentEvents_data() diff --git a/tests/auto/render/scene2d/tst_scene2d.cpp b/tests/auto/render/scene2d/tst_scene2d.cpp index fcb4c0908..ecade18fc 100644 --- a/tests/auto/render/scene2d/tst_scene2d.cpp +++ b/tests/auto/render/scene2d/tst_scene2d.cpp @@ -209,6 +209,7 @@ private Q_SLOTS: QScopedPointer testWindow(new TestWindow()); Scene2DSharedObjectPtr sharedObject(new Scene2DSharedObject(nullptr)); + TestRenderer renderer; QScopedPointer scene2d(new Scene2D()); QScopedPointer nodeManagers(new NodeManagers()); Qt3DRender::QGeometry *geometry = new Qt3DRender::QGeometry(); @@ -218,7 +219,6 @@ private Q_SLOTS: Qt3DRender::QBuffer *dataBuffer =new Qt3DRender::QBuffer(); QScopedPointer entity(new Qt3DCore::QEntity()); entity->addComponent(geometryRenderer); - TestRenderer renderer; renderer.setNodeManagers(nodeManagers.data()); scene2d->setRenderer(&renderer); scene2d->setEnabled(true); -- cgit v1.2.3 From fb2a38bb010bc30210e4a1ec211e24f263c889d1 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Feb 2020 08:03:13 +0100 Subject: tst_filtercompatibletechniquejob: skip test if unable to create context Change-Id: I79bfa9f14518427bc1211cc48f6561906b1653ce Reviewed-by: Paul Lemire --- .../tst_filtercompatibletechniquejob.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'tests') diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index 25262a772..1f88b49d1 100644 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -53,6 +53,7 @@ public: : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) , m_jobManager(new Qt3DCore::QAspectJobManager()) , m_window(new QWindow()) + , m_contextCreationSuccessful(false) { m_window->setSurfaceType(QWindow::OpenGLSurface); m_window->setGeometry(0, 0, 10, 10); @@ -68,6 +69,8 @@ public: return; } + m_contextCreationSuccessful = true; + Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); QRenderAspect::onRegistered(); @@ -100,6 +103,11 @@ public: ? d_func()->m_renderer->nodeManagers() : nullptr; } + bool contextCreationSuccessful() const + { + return m_contextCreationSuccessful; + } + void initializeRenderer() { renderer()->setOpenGLContext(&m_glContext); @@ -119,6 +127,7 @@ private: QScopedPointer m_jobManager; QScopedPointer m_window; QOpenGLContext m_glContext; + bool m_contextCreationSuccessful; }; } // namespace Qt3DRender @@ -211,6 +220,11 @@ private Q_SLOTS: Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; Qt3DRender::TestAspect testAspect(buildTestScene()); + const bool unableToCreateContext = !testAspect.contextCreationSuccessful(); + + if (unableToCreateContext) + QSKIP("Initialization failed, unable to create GL context"); + // WHEN Qt3DRender::Render::NodeManagers *nodeManagers = testAspect.nodeManagers(); QVERIFY(nodeManagers); -- cgit v1.2.3 From 118124ac1340efb64e8821d466f9d9c2be001bc2 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 3 Feb 2020 10:04:39 +0100 Subject: tst_filtercompatibletechniquejob: fix unregister in case context creation failed Change-Id: I7988ab2c918ecca694df996cc95cd9730d69a6cd Reviewed-by: Paul Lemire --- .../filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index 1f88b49d1..618709269 100644 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -94,7 +94,8 @@ public: ~TestAspect() { - QRenderAspect::onUnregistered(); + if (m_contextCreationSuccessful) + QRenderAspect::onUnregistered(); } Qt3DRender::Render::NodeManagers *nodeManagers() const -- cgit v1.2.3 From abf5d701ed90e3f1516821712a3018cbe7a2b7fe Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 2 Jun 2017 13:28:45 +0200 Subject: Add dedicated managers holder for GL Resources That way NodeManagers only refers to managers holding nodes (so can be used by aspect and all renderer) and GLResourceManagers refers to renderer specific resources. Note: the Scene2D resourceaccessor was making direct access to GL resource through the managers, this has been commented and will be restored later. Change-Id: Ic32784f60eac35aab8c066d1769f078639fa25b8 Reviewed-by: Mike Krus --- tests/auto/render/scene2d/tst_scene2d.cpp | 1 + tests/auto/render/textures/tst_textures.cpp | 33 ++++++++++++++++------------- 2 files changed, 19 insertions(+), 15 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/scene2d/tst_scene2d.cpp b/tests/auto/render/scene2d/tst_scene2d.cpp index fcb4c0908..3d943eae7 100644 --- a/tests/auto/render/scene2d/tst_scene2d.cpp +++ b/tests/auto/render/scene2d/tst_scene2d.cpp @@ -326,6 +326,7 @@ private Q_SLOTS: tri, v0, v1, v2, Qt3DRender::QPickEvent::LeftButton, Qt::LeftButton, 0, uvw) { + QSKIP("Disabled until Renderer plugin refactoring is complete"); // WHEN QVector3D uvw(1.0, 0.0f, 0.0f); Qt3DRender::QPickEventPtr ev = Qt3DRender::QPickEventPtr(PICK_TRIANGLE(0, 0, 1, 2, uvw)); diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp index 934cc8151..12d538772 100644 --- a/tests/auto/render/textures/tst_textures.cpp +++ b/tests/auto/render/textures/tst_textures.cpp @@ -38,11 +38,11 @@ QT_WARNING_DISABLE_DEPRECATED #include #include +#include #include #include #include #include -#include #include #include @@ -242,8 +242,8 @@ private Q_SLOTS: renderer.updateTexture(bt1b); // THEN - QCOMPARE(mgrs->glTextureManager()->lookupResource(bt1a->peerId()), mgrs->glTextureManager()->lookupResource(bt1b->peerId())); - + QCOMPARE(renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1a->peerId()), + renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1b->peerId())); renderer.shutdown(); } @@ -278,11 +278,12 @@ private Q_SLOTS: // no 2 textures must be the same for (int i = 0; i < backend.size(); i++) for (int k = i+1; k < backend.size(); k++) - QVERIFY(mgrs->glTextureManager()->lookupResource(backend[i]->peerId()) != mgrs->glTextureManager()->lookupResource(backend[k]->peerId())); + QVERIFY(renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[i]->peerId()) != + renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[k]->peerId())); QVector glTextures; for (Qt3DRender::Render::Texture *t : backend) - glTextures.push_back(mgrs->glTextureManager()->lookupResource(t->peerId())); + glTextures.push_back(renderer.glResourceManagers()->glTextureManager()->lookupResource(t->peerId())); // some texture generators must be the same QVERIFY(glTextures[0]->textureGenerator().data() == nullptr); @@ -308,6 +309,8 @@ private Q_SLOTS: Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(mgrs.data()); + Qt3DRender::Render::GLResourceManagers *glMgrs = renderer.glResourceManagers(); + // both texture having the same sharedTextureId { // GIVEN @@ -332,8 +335,8 @@ private Q_SLOTS: renderer.updateTexture(bt2); // THEN - Qt3DRender::Render::GLTexture *glt1 = mgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = mgrs->glTextureManager()->lookupResource(bt2->peerId()); + Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); QVERIFY(glt1 != glt2); QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); @@ -363,8 +366,8 @@ private Q_SLOTS: renderer.updateTexture(bt2); // THEN - Qt3DRender::Render::GLTexture *glt1 = mgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = mgrs->glTextureManager()->lookupResource(bt2->peerId()); + Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); QVERIFY(glt1 != glt2); QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); @@ -396,12 +399,12 @@ private Q_SLOTS: renderer.updateTexture(backendTexture); } - Qt3DRender::QTextureImageDataGeneratorPtr idg1a = mgrs->glTextureManager()->lookupResource(backend[0]->peerId())->images()[0].generator; - Qt3DRender::QTextureImageDataGeneratorPtr idg1b = mgrs->glTextureManager()->lookupResource(backend[1]->peerId())->images()[0].generator; - Qt3DRender::QTextureImageDataGeneratorPtr idg2 = mgrs->glTextureManager()->lookupResource(backend[1]->peerId())->images()[1].generator; - Qt3DRender::QTextureGeneratorPtr tg1a = mgrs->glTextureManager()->lookupResource(backend[0]->peerId())->textureGenerator(); - Qt3DRender::QTextureGeneratorPtr tg1b = mgrs->glTextureManager()->lookupResource(backend[2]->peerId())->textureGenerator(); - Qt3DRender::QTextureGeneratorPtr tg2 = mgrs->glTextureManager()->lookupResource(backend[1]->peerId())->textureGenerator(); + Qt3DRender::QTextureImageDataGeneratorPtr idg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->images()[0].generator; + Qt3DRender::QTextureImageDataGeneratorPtr idg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[0].generator; + Qt3DRender::QTextureImageDataGeneratorPtr idg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[1].generator; + Qt3DRender::QTextureGeneratorPtr tg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->textureGenerator(); + Qt3DRender::QTextureGeneratorPtr tg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[2]->peerId())->textureGenerator(); + Qt3DRender::QTextureGeneratorPtr tg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->textureGenerator(); // THEN QVERIFY(idg1a); -- cgit v1.2.3 From 9124a61eb1c10ed3bb7251baf2f42ac4a865e514 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Wed, 7 Jun 2017 10:49:04 +0200 Subject: Introduce a GLShader class GLShader is renderer specific shader implementation for OpenGL. Shader now contains only backend information for a QShaderProgram frontend node. - Similar to the GLTexture handling, a generic adopt/abandon manager for shaders was introduced (regardless of the actually GraphicsAPIShader class). - The renderer and renderviews were adapted to the new changes. This was the last major thing preventing the modularisation of the QRenderAspect and renderers Change-Id: If671d60928b433977e9d6e5c58199827f9408a3f Task-number: QTBUG-61151 Reviewed-by: Mike Krus --- .../render/glshadermanager/glshadermanager.pro | 12 + .../render/glshadermanager/tst_glshadermanager.cpp | 199 ++++++++++++++ tests/auto/render/render.pro | 2 +- tests/auto/render/renderviews/tst_renderviews.cpp | 111 ++++++-- tests/auto/render/shader/tst_shader.cpp | 46 +--- tests/auto/render/shadercache/shadercache.pro | 11 - tests/auto/render/shadercache/tst_shadercache.cpp | 293 --------------------- 7 files changed, 308 insertions(+), 366 deletions(-) create mode 100644 tests/auto/render/glshadermanager/glshadermanager.pro create mode 100644 tests/auto/render/glshadermanager/tst_glshadermanager.cpp delete mode 100644 tests/auto/render/shadercache/shadercache.pro delete mode 100644 tests/auto/render/shadercache/tst_shadercache.cpp (limited to 'tests') diff --git a/tests/auto/render/glshadermanager/glshadermanager.pro b/tests/auto/render/glshadermanager/glshadermanager.pro new file mode 100644 index 000000000..27aadf84f --- /dev/null +++ b/tests/auto/render/glshadermanager/glshadermanager.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_glshadermanager + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_glshadermanager.cpp + +include(../../core/common/common.pri) +include(../commons/commons.pri) diff --git a/tests/auto/render/glshadermanager/tst_glshadermanager.cpp b/tests/auto/render/glshadermanager/tst_glshadermanager.cpp new file mode 100644 index 000000000..c18fb4793 --- /dev/null +++ b/tests/auto/render/glshadermanager/tst_glshadermanager.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_GLShaderManager : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void adopt(); + void lookupResource(); + void abandon(); + void insertAfterRemoval(); +}; + +void tst_GLShaderManager::adopt() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + + // THEN + QVERIFY(cache.lookupResource(backendShaderNode1.peerId()) == nullptr); + QVERIFY(cache.lookupResource(backendShaderNode2.peerId()) == nullptr); + QVERIFY(backendShaderNode1.peerId() != backendShaderNode2.peerId()); + + // WHEN + Qt3DRender::Render::GLShader *glShader1 = cache.createOrAdoptExisting(&backendShaderNode1); + + // THEN + QVERIFY(glShader1 != nullptr); + QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); + QCOMPARE(shaderNodeIds.size(), 1); + QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); + + // WHEN + Qt3DRender::Render::GLShader *glShader2 = cache.createOrAdoptExisting(&backendShaderNode2); + + // THEN + QCOMPARE(glShader1, glShader2); + + shaderNodeIds = cache.shaderIdsForProgram(glShader2); + QCOMPARE(shaderNodeIds.size(), 2); + QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); + QCOMPARE(shaderNodeIds.last(), backendShaderNode2.peerId()); +} + +void tst_GLShaderManager::lookupResource() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + + // WHEN + cache.createOrAdoptExisting(&backendShaderNode1); + cache.createOrAdoptExisting(&backendShaderNode2); + + // THEN + Qt3DRender::Render::GLShader *glShader1 = cache.lookupResource(backendShaderNode1.peerId()); + Qt3DRender::Render::GLShader *glShader2 = cache.lookupResource(backendShaderNode2.peerId()); + QVERIFY(glShader1 != nullptr); + QCOMPARE(glShader1, glShader2); + const QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); + QCOMPARE(shaderNodeIds.size(), 2); + QVERIFY(shaderNodeIds.contains(frontendShader1.id())); + QVERIFY(shaderNodeIds.contains(frontendShader2.id())); +} + +void tst_GLShaderManager::abandon() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + cache.createOrAdoptExisting(&backendShaderNode1); + cache.createOrAdoptExisting(&backendShaderNode2); + + // WHEN + Qt3DRender::Render::GLShader *glShader = cache.lookupResource(backendShaderNode1.peerId()); + cache.abandon(glShader, &backendShaderNode1); + + // THEN + QVector shaderNodeIds = cache.shaderIdsForProgram(glShader); + QVERIFY(cache.takeAbandonned().isEmpty()); + QCOMPARE(shaderNodeIds.size(), 1); + QCOMPARE(shaderNodeIds.first(), backendShaderNode2.peerId()); + + // WHEN + cache.abandon(glShader, &backendShaderNode2); + + // THEN + shaderNodeIds = cache.shaderIdsForProgram(glShader); + QCOMPARE(shaderNodeIds.size(), 0); + const QVector releasedShaders = cache.takeAbandonned(); + QCOMPARE(releasedShaders.size(), 1); + QCOMPARE(releasedShaders.first(), glShader); +} + +void tst_GLShaderManager::insertAfterRemoval() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode; + + + backendShaderNode.setRenderer(&renderer); + simulateInitialization(&frontendShader, &backendShaderNode); + + // WHEN + Qt3DRender::Render::GLShader *apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); + const Qt3DRender::Render::GLShader *originalApiShader = apiShader1; + + // THEN + auto apiShader2 = cache.lookupResource(frontendShader.id()); + QVERIFY(apiShader1 != nullptr); + QVERIFY(apiShader2 != nullptr); + QVERIFY(apiShader1 == originalApiShader); + QVERIFY(apiShader1 == apiShader2); + + // WHEN + cache.abandon(apiShader1, &backendShaderNode); + + // THEN + Qt3DRender::Render::GLShader *apiShaderEmpty = cache.lookupResource(frontendShader.id()); + QVERIFY(apiShaderEmpty == nullptr); + + // WHEN + apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); + cache.purge(); + apiShader2 = cache.lookupResource(frontendShader.id()); + + // THEN + QVERIFY(apiShader1 != nullptr); + QVERIFY(apiShader2 != nullptr); + QVERIFY(apiShader1 == apiShader2); + QVERIFY(apiShader2 == originalApiShader); +} + +QTEST_APPLESS_MAIN(tst_GLShaderManager) + +#include "tst_glshadermanager.moc" diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 908426570..2b73ec8b7 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -42,7 +42,6 @@ qtConfig(private_tests) { # boundingvolumedebug \ ddstextures \ ktxtextures \ - shadercache \ layerfiltering \ filterentitybycomponent \ genericlambdajob \ @@ -130,6 +129,7 @@ qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) { graphicshelpergl3_3 \ graphicshelpergl3_2 \ graphicshelpergl2 \ + glshadermanager \ materialparametergathererjob \ textures \ renderer \ diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp index 086ff0220..b434fe83a 100644 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/renderviews/tst_renderviews.cpp @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include QT_BEGIN_NAMESPACE @@ -64,6 +67,7 @@ void compareShaderParameterPacks(const ShaderParameterPack &t1, class tst_RenderViews : public Qt3DCore::QBackendNodeTester { Q_OBJECT + private Q_SLOTS: void checkRenderViewSizeFitsWithAllocator() @@ -132,10 +136,15 @@ private Q_SLOTS: void checkRenderCommandBackToFrontSorting() { // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + sortTypes.push_back(QSortPolicy::BackToFront); for (int i = 0; i < 200; ++i) { @@ -156,28 +165,34 @@ private Q_SLOTS: QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth); // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); } void checkRenderCommandMaterialSorting() { // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + sortTypes.push_back(QSortPolicy::Material); - ProgramDNA dnas[5] = { - ProgramDNA(250), - ProgramDNA(500), - ProgramDNA(1000), - ProgramDNA(1500), - ProgramDNA(2000), + GLShader *dnas[5] = { + reinterpret_cast(0x250), + reinterpret_cast(0x500), + reinterpret_cast(0x1000), + reinterpret_cast(0x1500), + reinterpret_cast(0x2000) }; for (int i = 0; i < 20; ++i) { RenderCommand c; - c.m_shaderDna = dnas[i % 5]; + c.m_glShader = dnas[i % 5]; rawCommands.push_back(c); } @@ -189,24 +204,25 @@ private Q_SLOTS: // THEN const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands.size(), sortedCommands.size()); - ProgramDNA targetDNA; + GLShader *targetShader; for (int j = 0; j < sortedCommands.size(); ++j) { if (j % 4 == 0) { - targetDNA = sortedCommands.at(j).m_shaderDna; + targetShader = sortedCommands.at(j).m_glShader; if (j > 0) - QVERIFY(targetDNA != sortedCommands.at(j - 1).m_shaderDna); + QVERIFY(targetShader != sortedCommands.at(j - 1).m_glShader); } - QCOMPARE(targetDNA, sortedCommands.at(j).m_shaderDna); + QCOMPARE(targetShader, sortedCommands.at(j).m_glShader); } // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); } void checkRenderViewUniformMinification_data() { - QTest::addColumn>("programDNAs"); + QTest::addColumn>("shaders"); QTest::addColumn>("rawParameters"); QTest::addColumn>("expectedMinimizedParameters"); @@ -217,36 +233,56 @@ private Q_SLOTS: pack1.setUniform(2, UniformValue(1584.0f)); pack1.setTexture(3, 0, fakeTextureNodeId); + QShaderProgram *shader1 = new QShaderProgram(); + QShaderProgram *shader2 = new QShaderProgram(); + + shader1->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("1")); + shader2->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("2")); + ShaderParameterPack minifiedPack1; QTest::newRow("NoMinification") - << (QVector() << ProgramDNA(883) << ProgramDNA(1584)) + << (QVector() << shader1 << shader2) << (QVector() << pack1 << pack1) << (QVector() << pack1 << pack1); QTest::newRow("SingleShaderMinified") - << (QVector() << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(883)) + << (QVector() << shader1 << shader1 << shader1) << (QVector() << pack1 << pack1 << pack1) << (QVector() << pack1 << minifiedPack1 << minifiedPack1); QTest::newRow("MultipleShadersMinified") - << (QVector() << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(883) << ProgramDNA(1584) << ProgramDNA(1584) << ProgramDNA(1584)) + << (QVector() << shader1 << shader1 << shader1 << shader2 << shader2 << shader2) << (QVector() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1) << (QVector() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1); } void checkRenderViewUniformMinification() { - QFETCH(QVector, programDNAs); + QFETCH(QVector, shaders); QFETCH(QVector, rawParameters); QFETCH(QVector, expectedMinimizedParameters); + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(&nodeManagers); + + GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager(); + for (int i = 0, m = shaders.size(); i < m; ++i) { + Shader* backend = new Shader(); + backend->setRenderer(&renderer); + simulateInitializationSync(shaders.at(i), backend); + shaderManager->createOrAdoptExisting(backend); + } + RenderView renderView; QVector rawCommands; + renderView.setRenderer(&renderer); - for (int i = 0, m = programDNAs.size(); i < m; ++i) { + for (int i = 0, m = shaders.size(); i < m; ++i) { RenderCommand c; - c.m_shaderDna = programDNAs.at(i); + c.m_shaderId = shaders.at(i)->id(); + c.m_glShader = shaderManager->lookupResource(c.m_shaderId); c.m_parameterPack = rawParameters.at(i); rawCommands.push_back(c); } @@ -260,21 +296,28 @@ private Q_SLOTS: const QVector sortedCommands = renderView.commands(); QCOMPARE(rawCommands, sortedCommands); - for (int i = 0, m = programDNAs.size(); i < m; ++i) { + for (int i = 0, m = shaders.size(); i < m; ++i) { const RenderCommand c = sortedCommands.at(i); - QCOMPARE(c.m_shaderDna, programDNAs.at(i)); + QCOMPARE(c.m_shaderId, shaders.at(i)->id()); compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); } + + renderer.shutdown(); } void checkRenderCommandFrontToBackSorting() { // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + sortTypes.push_back(QSortPolicy::FrontToBack); for (int i = 0; i < 200; ++i) { @@ -295,15 +338,21 @@ private Q_SLOTS: QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth); // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); } void checkRenderCommandStateCostSorting() { // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + sortTypes.push_back(QSortPolicy::StateChangeCost); for (int i = 0; i < 200; ++i) { @@ -324,24 +373,31 @@ private Q_SLOTS: QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost); // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); } void checkRenderCommandCombinedStateMaterialDepthSorting() { // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + sortTypes.push_back(QSortPolicy::StateChangeCost); sortTypes.push_back(QSortPolicy::Material); sortTypes.push_back(QSortPolicy::BackToFront); - ProgramDNA dna[4] = { - ProgramDNA(250), - ProgramDNA(500), - ProgramDNA(1000), - ProgramDNA(1500) + GLShader *dna[5] = { + reinterpret_cast(0x250), + reinterpret_cast(0x500), + reinterpret_cast(0x1000), + reinterpret_cast(0x1500), + reinterpret_cast(0x2000) }; float depth[3] = { @@ -355,9 +411,9 @@ private Q_SLOTS: 200 }; - auto buildRC = [] (ProgramDNA dna, float depth, int changeCost) { + auto buildRC = [] (GLShader *dna, float depth, int changeCost) { RenderCommand c; - c.m_shaderDna = dna; + c.m_glShader = dna; c.m_depth = depth; c.m_changeCost = changeCost; return c; @@ -400,6 +456,7 @@ private Q_SLOTS: QCOMPARE(c9, sortedCommands.at(6)); // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); } void checkRenderCommandTextureSorting() diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp index d1578aee7..3f0714907 100644 --- a/tests/auto/render/shader/tst_shader.cpp +++ b/tests/auto/render/shader/tst_shader.cpp @@ -79,15 +79,9 @@ void tst_RenderShader::hasCoherentInitialState() { Qt3DRender::Render::Shader *shader = new Qt3DRender::Render::Shader(); - QCOMPARE(shader->isLoaded(), false); - QCOMPARE(shader->dna(), 0U); - QVERIFY(shader->uniformsNames().isEmpty()); - QVERIFY(shader->attributesNames().isEmpty()); - QVERIFY(shader->uniformBlockNames().isEmpty()); - QVERIFY(shader->uniforms().isEmpty()); - QVERIFY(shader->attributes().isEmpty()); - QVERIFY(shader->uniformBlocks().isEmpty()); QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); + QVERIFY(shader->log().isEmpty()); + QCOMPARE(shader->isDirty(), false); } void tst_RenderShader::matchesFrontendPeer() @@ -98,8 +92,7 @@ void tst_RenderShader::matchesFrontendPeer() backend.setRenderer(&renderer); simulateInitializationSync(frontend.data(), &backend); - QCOMPARE(backend.isLoaded(), false); - QVERIFY(backend.dna() != 0U); + QCOMPARE(backend.isDirty(), true); for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i) QCOMPARE(backend.shaderCode()[i], @@ -117,14 +110,7 @@ void tst_RenderShader::cleanupLeavesACoherentState() shader.cleanup(); - QCOMPARE(shader.isLoaded(), false); - QCOMPARE(shader.dna(), 0U); - QVERIFY(shader.uniformsNames().isEmpty()); - QVERIFY(shader.attributesNames().isEmpty()); - QVERIFY(shader.uniformBlockNames().isEmpty()); - QVERIFY(shader.uniforms().isEmpty()); - QVERIFY(shader.attributes().isEmpty()); - QVERIFY(shader.uniformBlocks().isEmpty()); + QCOMPARE(shader.isDirty(), false); QCOMPARE(shader.status(), Qt3DRender::QShaderProgram::NotReady); } @@ -152,7 +138,7 @@ void tst_RenderShader::dealWithPropertyChanges() Qt3DRender::Render::Shader backend; Qt3DRender::QShaderProgram shader; - backend.setLoaded(true); + TestRenderer renderer; backend.setRenderer(&renderer); simulateInitializationSync(&shader, &backend); @@ -162,11 +148,13 @@ void tst_RenderShader::dealWithPropertyChanges() backend.syncFromFrontEnd(&shader, false); // THEN - QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("foo")); - QVERIFY(!backend.isLoaded()); + QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + QCOMPARE(backend.isDirty(), true); + renderer.resetDirty(); - backend.setLoaded(true); + QCOMPARE(renderer.dirtyBits(), 0); + backend.unsetDirty(); // WHEN shader.setShaderCode(type, QByteArrayLiteral("foo")); @@ -174,10 +162,8 @@ void tst_RenderShader::dealWithPropertyChanges() // THEN QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("foo")); - QVERIFY(backend.isLoaded()); QCOMPARE(renderer.dirtyBits(), 0); - renderer.resetDirty(); - backend.setLoaded(true); + QCOMPARE(backend.isDirty(), false); // WHEN shader.setShaderCode(type, QByteArrayLiteral("bar")); @@ -185,10 +171,9 @@ void tst_RenderShader::dealWithPropertyChanges() // THEN QCOMPARE(backend.shaderCode().at(type), QByteArrayLiteral("bar")); - QVERIFY(!backend.isLoaded()); QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); renderer.resetDirty(); - backend.setLoaded(true); + QCOMPARE(backend.isDirty(), true); } void tst_RenderShader::checkSetRendererDirtyOnInitialization() @@ -221,7 +206,6 @@ void tst_RenderShader::allowToChangeShaderCode() QFETCH(Qt3DRender::QShaderProgram::ShaderType, type); Qt3DRender::Render::Shader backend; - backend.setLoaded(true); TestRenderer renderer; backend.setRenderer(&renderer); @@ -230,30 +214,24 @@ void tst_RenderShader::allowToChangeShaderCode() // THEN QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); - QVERIFY(!backend.isLoaded()); QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); renderer.resetDirty(); - backend.setLoaded(true); // WHEN backend.setShaderCode(type, QByteArrayLiteral("foo")); // THEN QCOMPARE(backend.shaderCode().at(type), QStringLiteral("foo")); - QVERIFY(backend.isLoaded()); QCOMPARE(renderer.dirtyBits(), 0); renderer.resetDirty(); - backend.setLoaded(true); // WHEN backend.setShaderCode(type, QByteArrayLiteral("bar")); // THEN QCOMPARE(backend.shaderCode().at(type), QStringLiteral("bar")); - QVERIFY(!backend.isLoaded()); QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); renderer.resetDirty(); - backend.setLoaded(true); } QTEST_APPLESS_MAIN(tst_RenderShader) diff --git a/tests/auto/render/shadercache/shadercache.pro b/tests/auto/render/shadercache/shadercache.pro deleted file mode 100644 index 38499588d..000000000 --- a/tests/auto/render/shadercache/shadercache.pro +++ /dev/null @@ -1,11 +0,0 @@ -TEMPLATE = app - -TARGET = tst_shadercache - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_shadercache.cpp - -include(../../core/common/common.pri) diff --git a/tests/auto/render/shadercache/tst_shadercache.cpp b/tests/auto/render/shadercache/tst_shadercache.cpp deleted file mode 100644 index 261548d69..000000000 --- a/tests/auto/render/shadercache/tst_shadercache.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -using namespace Qt3DCore; - -namespace Qt3DRender { -namespace Render { - -class tst_ShaderCache : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void insert(); - void insertAfterRemoval(); - void value(); - void removeRef(); - void purge(); - void destruction(); -}; - -void tst_ShaderCache::insert() -{ - // GIVEN - ShaderCache cache; - - // THEN - QCOMPARE(cache.m_programHash.isEmpty(), true); - QCOMPARE(cache.m_programRefs.isEmpty(), true); - QCOMPARE(cache.m_pendingRemoval.isEmpty(), true); - - // WHEN - auto dna = ProgramDNA(12345); - auto nodeId = QNodeId::createId(); - auto shaderProgram = new QOpenGLShaderProgram; - cache.insert(dna, nodeId, shaderProgram); - - // THEN - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programHash.keys().first(), dna); - QCOMPARE(cache.m_programHash.values().first(), shaderProgram); - - QCOMPARE(cache.m_programRefs.size(), 1); - QCOMPARE(cache.m_programRefs.keys().first(), dna); - QCOMPARE(cache.m_programRefs.values().first().size(), 1); - QCOMPARE(cache.m_programRefs.values().first().first(), nodeId); - - QCOMPARE(cache.m_pendingRemoval.isEmpty(), true); -} - -void tst_ShaderCache::insertAfterRemoval() -{ - // GIVEN - ShaderCache cache; - auto dna = ProgramDNA(12345); - auto nodeId = QNodeId::createId(); - - // WHEN - QOpenGLShaderProgram *shaderProgram = new QOpenGLShaderProgram(); - cache.insert(dna, nodeId, shaderProgram); - cache.getShaderProgramAndAddRef(dna, nodeId); - cache.removeRef(dna, nodeId); - shaderProgram = cache.getShaderProgramAndAddRef(dna, nodeId); - - // THEN - QVERIFY(!cache.m_pendingRemoval.contains(dna)); - - // WHEN - cache.removeRef(dna, nodeId); - cache.getShaderProgramAndAddRef(dna, nodeId); - cache.purge(); - - // THEN - QCOMPARE(cache.m_programHash.size(), 1); -} - -void tst_ShaderCache::value() -{ - // GIVEN - ShaderCache cache; - - // WHEN - auto dnaA = ProgramDNA(12345); - auto nodeIdA = QNodeId::createId(); - auto shaderProgramA = new QOpenGLShaderProgram; - cache.insert(dnaA, nodeIdA, shaderProgramA); - auto cachedProgramA = cache.getShaderProgramAndAddRef(dnaA, nodeIdA); - - // THEN - QCOMPARE(shaderProgramA, cachedProgramA); - - // WHEN - auto nodeIdA2 = QNodeId::createId(); - auto cachedProgramA2 = cache.getShaderProgramAndAddRef(dnaA, nodeIdA2); - - // THEN - QCOMPARE(shaderProgramA, cachedProgramA2); - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programHash.keys().first(), dnaA); - QCOMPARE(cache.m_programHash.values().first(), shaderProgramA); - - QCOMPARE(cache.m_programRefs.size(), 1); - QCOMPARE(cache.m_programRefs.keys().first(), dnaA); - const QVector refsA = cache.m_programRefs.values().first(); - QCOMPARE(refsA.size(), 2); - QCOMPARE(refsA.at(0), nodeIdA); - QCOMPARE(refsA.at(1), nodeIdA2); - - // WHEN - auto dnaB = ProgramDNA(67890); - auto nodeIdB = QNodeId::createId(); - auto shaderProgramB = new QOpenGLShaderProgram; - cache.insert(dnaB, nodeIdB, shaderProgramB); - - // THEN - QCOMPARE(cache.m_programHash.size(), 2); - QCOMPARE(cache.m_programRefs.size(), 2); - - // WHEN - auto cachedProgramB = cache.getShaderProgramAndAddRef(dnaB, nodeIdB); - QCOMPARE(shaderProgramB, cachedProgramB); - - // WHEN - auto dnaC = ProgramDNA(54321); - auto uncachedProgram = cache.getShaderProgramAndAddRef(dnaC, nodeIdB); - QVERIFY(uncachedProgram == nullptr); - - cache.clear(); - // Test inserting nullptr. - cache.insert(dnaA, nodeIdA, nullptr); - bool wasPresent = false; - cachedProgramA = cache.getShaderProgramAndAddRef(dnaA, nodeIdA, &wasPresent); - QCOMPARE(wasPresent, true); - QCOMPARE(cachedProgramA, nullptr); - cache.clear(); - // Test wasPresent==false. - cachedProgramB = cache.getShaderProgramAndAddRef(dnaB, nodeIdB, &wasPresent); - QCOMPARE(wasPresent, false); - QCOMPARE(cachedProgramB, nullptr); -} - -void tst_ShaderCache::removeRef() -{ - // GIVEN - ShaderCache cache; - - // WHEN we add 2 references and remove one - auto dnaA = ProgramDNA(12345); - auto nodeIdA = QNodeId::createId(); - auto shaderProgramA = new QOpenGLShaderProgram; - cache.insert(dnaA, nodeIdA, shaderProgramA); - auto cachedProgramA = cache.getShaderProgramAndAddRef(dnaA, nodeIdA); - - auto nodeIdA2 = QNodeId::createId(); - auto cachedProgramA2 = cache.getShaderProgramAndAddRef(dnaA, nodeIdA2); - - cache.removeRef(dnaA, nodeIdA); - - // THEN - QCOMPARE(cachedProgramA, shaderProgramA); - QCOMPARE(cachedProgramA2, shaderProgramA); - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programRefs.size(), 1); - const auto refs = cache.m_programRefs.value(dnaA); - QCOMPARE(refs.size(), 1); - QCOMPARE(refs.first(), nodeIdA2); - QCOMPARE(cache.m_pendingRemoval.size(), 0); - - // WHEN we remove same ref again - cache.removeRef(dnaA, nodeIdA); - - // THEN no change - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programRefs.size(), 1); - const auto refs2 = cache.m_programRefs.value(dnaA); - QCOMPARE(refs2.size(), 1); - QCOMPARE(refs.first(), nodeIdA2); - - // WHEN we remove other reference - cache.removeRef(dnaA, nodeIdA2); - - // THEN - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programRefs.size(), 1); - const auto refs3 = cache.m_programRefs.value(dnaA); - QCOMPARE(refs3.size(), 0); - QCOMPARE(cache.m_pendingRemoval.size(), 1); - QCOMPARE(cache.m_pendingRemoval.first(), dnaA); -} - -void tst_ShaderCache::purge() -{ - // GIVEN - ShaderCache cache; - - // WHEN we add 2 references and remove one and purge - auto dnaA = ProgramDNA(12345); - auto nodeIdA = QNodeId::createId(); - auto shaderProgramA = new QOpenGLShaderProgram; - QPointer progPointer(shaderProgramA); - cache.insert(dnaA, nodeIdA, shaderProgramA); - auto cachedProgramA = cache.getShaderProgramAndAddRef(dnaA, nodeIdA); - - auto nodeIdA2 = QNodeId::createId(); - auto cachedProgramA2 = cache.getShaderProgramAndAddRef(dnaA, nodeIdA2); - - cache.removeRef(dnaA, nodeIdA); - cache.purge(); - - // THEN no removal - QCOMPARE(cachedProgramA, shaderProgramA); - QCOMPARE(cachedProgramA2, shaderProgramA); - QCOMPARE(cache.m_programHash.size(), 1); - QCOMPARE(cache.m_programRefs.size(), 1); - QCOMPARE(cache.m_pendingRemoval.isEmpty(), true); - - // WHEN we remove final ref and purge - cache.removeRef(dnaA, nodeIdA2); - cache.purge(); - - // THEN shader program is removed from cache and deleted - QCOMPARE(cache.m_programHash.isEmpty(), true); - QCOMPARE(cache.m_programRefs.isEmpty(), true); - QCOMPARE(progPointer.isNull(), true); -} - -void tst_ShaderCache::destruction() -{ - // GIVEN - auto cache = new ShaderCache; - - // WHEN - auto dnaA = ProgramDNA(12345); - auto nodeIdA = QNodeId::createId(); - auto shaderProgramA = new QOpenGLShaderProgram; - QPointer progPointerA(shaderProgramA); - - auto dnaB = ProgramDNA(67890); - auto nodeIdB = QNodeId::createId(); - auto shaderProgramB = new QOpenGLShaderProgram; - QPointer progPointerB(shaderProgramB); - - cache->insert(dnaA, nodeIdA, shaderProgramA); - cache->insert(dnaB, nodeIdB, shaderProgramB); - delete cache; - - // THEN - QCOMPARE(progPointerA.isNull(), true); - QCOMPARE(progPointerB.isNull(), true); -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -QTEST_APPLESS_MAIN(Qt3DRender::Render::tst_ShaderCache) - -#include "tst_shadercache.moc" -- cgit v1.2.3 From 17822c91e7f128b5d9af525cd638c9a4d35ea8fb Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 24 Aug 2017 07:20:26 +0200 Subject: QShaderProgram: add a format property Can be either GLSL (default) or SPIRV at the moment. This variable will be used by the rendering backend to know what type of shader code was provided (e.g with Vulkan, the GLSL could be internally converted to SPIRV) Change-Id: I1f9b734a675c581ef0721edc4464e466a18afbb0 Reviewed-by: Paul Lemire --- .../render/qshaderprogram/tst_qshaderprogram.cpp | 65 ++++++++++++++++++++++ tests/auto/render/shader/tst_shader.cpp | 48 +++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp index 18dd1306a..15be26e8e 100644 --- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp +++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp @@ -45,6 +45,13 @@ class tst_QShaderProgram : public Qt3DRender::QShaderProgram { Q_OBJECT +public: + tst_QShaderProgram() + : Qt3DRender::QShaderProgram() + { + qRegisterMetaType("Format"); + } + private Q_SLOTS: void checkDefaultConstruction() @@ -61,6 +68,7 @@ private Q_SLOTS: QCOMPARE(shaderProgram.computeShaderCode(), QByteArray()); QCOMPARE(shaderProgram.log(), QString()); QCOMPARE(shaderProgram.status(), Qt3DRender::QShaderProgram::NotReady); + QCOMPARE(shaderProgram.format(), Qt3DRender::QShaderProgram::GLSL); } void checkPropertyChanges() @@ -182,6 +190,25 @@ private Q_SLOTS: QCOMPARE(shaderProgram.computeShaderCode(), newValue); QCOMPARE(spy.count(), 0); } + { + // WHEN + QSignalSpy spy(&shaderProgram, SIGNAL(formatChanged(Format))); + const QShaderProgram::Format newValue = QShaderProgram::SPIRV; + shaderProgram.setFormat(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(shaderProgram.format(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + shaderProgram.setFormat(newValue); + + // THEN + QCOMPARE(shaderProgram.format(), newValue); + QCOMPARE(spy.count(), 0); + } } void checkCreationData() @@ -195,6 +222,7 @@ private Q_SLOTS: shaderProgram.setGeometryShaderCode(QByteArrayLiteral("Geometry")); shaderProgram.setFragmentShaderCode(QByteArrayLiteral("Fragment")); shaderProgram.setComputeShaderCode(QByteArrayLiteral("Compute")); + shaderProgram.setFormat(QShaderProgram::SPIRV); // WHEN QVector creationChanges; @@ -217,6 +245,7 @@ private Q_SLOTS: QCOMPARE(shaderProgram.geometryShaderCode(), cloneData.geometryShaderCode); QCOMPARE(shaderProgram.fragmentShaderCode(), cloneData.fragmentShaderCode); QCOMPARE(shaderProgram.computeShaderCode(), cloneData.computeShaderCode); + QCOMPARE(shaderProgram.format(), cloneData.format); QCOMPARE(shaderProgram.id(), creationChangeData->subjectId()); QCOMPARE(shaderProgram.isEnabled(), true); QCOMPARE(shaderProgram.isEnabled(), creationChangeData->isNodeEnabled()); @@ -532,6 +561,42 @@ private Q_SLOTS: // THEN QVERIFY(mainContent.indexOf(includedContent) == 0); } + + void checkFormatPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DRender::QShaderProgram shaderProgram; + arbiter.setArbiterOnNode(&shaderProgram); + + QSignalSpy spy(&shaderProgram, SIGNAL(formatChanged(Format))); + + // THEN + QVERIFY(spy.isValid()); + + { + // WHEN + shaderProgram.setFormat(QShaderProgram::SPIRV); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(spy.count(), 1); + QCOMPARE(arbiter.events.size(), 0); + + spy.clear(); + } + + { + // WHEN + shaderProgram.setFormat(QShaderProgram::SPIRV); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(spy.count(), 0); + QCOMPARE(arbiter.events.size(), 0); + } + } + }; QTEST_MAIN(tst_QShaderProgram) diff --git a/tests/auto/render/shader/tst_shader.cpp b/tests/auto/render/shader/tst_shader.cpp index 3f0714907..a1f837010 100644 --- a/tests/auto/render/shader/tst_shader.cpp +++ b/tests/auto/render/shader/tst_shader.cpp @@ -42,15 +42,17 @@ private slots: void cleanupLeavesACoherentState(); void dealWithPropertyChanges_data(); void dealWithPropertyChanges(); + void dealWithFormatChanges(); void checkSetRendererDirtyOnInitialization(); void allowToChangeShaderCode_data(); void allowToChangeShaderCode(); }; -Qt3DRender::QShaderProgram *createFrontendShader() +Qt3DRender::QShaderProgram *createFrontendShader(Qt3DRender::QShaderProgram::Format format = Qt3DRender::QShaderProgram::GLSL) { Qt3DRender::QShaderProgram *shader = new Qt3DRender::QShaderProgram(); + shader->setFormat(format); shader->setVertexShaderCode(QByteArrayLiteral( "#version 150"\ @@ -80,6 +82,7 @@ void tst_RenderShader::hasCoherentInitialState() Qt3DRender::Render::Shader *shader = new Qt3DRender::Render::Shader(); QCOMPARE(shader->status(), Qt3DRender::QShaderProgram::NotReady); + QCOMPARE(shader->format(), Qt3DRender::QShaderProgram::GLSL); QVERIFY(shader->log().isEmpty()); QCOMPARE(shader->isDirty(), false); } @@ -97,11 +100,12 @@ void tst_RenderShader::matchesFrontendPeer() for (int i = Qt3DRender::QShaderProgram::Vertex; i <= Qt3DRender::QShaderProgram::Compute; ++i) QCOMPARE(backend.shaderCode()[i], frontend->shaderCode(static_cast(i))); + QCOMPARE(backend.format(), frontend->format()); } void tst_RenderShader::cleanupLeavesACoherentState() { - QScopedPointer frontend(createFrontendShader()); + QScopedPointer frontend(createFrontendShader(Qt3DRender::QShaderProgram::SPIRV)); TestRenderer renderer; Qt3DRender::Render::Shader shader; @@ -112,6 +116,7 @@ void tst_RenderShader::cleanupLeavesACoherentState() QCOMPARE(shader.isDirty(), false); QCOMPARE(shader.status(), Qt3DRender::QShaderProgram::NotReady); + QCOMPARE(shader.format(), Qt3DRender::QShaderProgram::GLSL); } void tst_RenderShader::dealWithPropertyChanges_data() @@ -176,6 +181,45 @@ void tst_RenderShader::dealWithPropertyChanges() QCOMPARE(backend.isDirty(), true); } +void tst_RenderShader::dealWithFormatChanges() +{ + // GIVEN + Qt3DRender::Render::Shader backend; + Qt3DRender::QShaderProgram shader; + TestRenderer renderer; + backend.setRenderer(&renderer); + simulateInitializationSync(&shader, &backend); + + // WHEN + shader.setFormat(Qt3DRender::QShaderProgram::GLSL); + backend.syncFromFrontEnd(&shader, false); + + // THEN + QCOMPARE(backend.format(), Qt3DRender::QShaderProgram::GLSL); + QCOMPARE(backend.isDirty(), false); + QCOMPARE(renderer.dirtyBits(), 0); + + // WHEN + shader.setFormat(Qt3DRender::QShaderProgram::SPIRV); + backend.syncFromFrontEnd(&shader, false); + + // THEN + QCOMPARE(backend.format(), Qt3DRender::QShaderProgram::SPIRV); + QCOMPARE(renderer.dirtyBits(), Qt3DRender::Render::AbstractRenderer::ShadersDirty); + QCOMPARE(backend.isDirty(), true); + + renderer.resetDirty(); + backend.unsetDirty(); + + // WHEN + shader.setFormat(Qt3DRender::QShaderProgram::SPIRV); + backend.syncFromFrontEnd(&shader, false); + + // THEN + QCOMPARE(backend.isDirty(), false); + QCOMPARE(renderer.dirtyBits(), 0); +} + void tst_RenderShader::checkSetRendererDirtyOnInitialization() { // GIVEN -- cgit v1.2.3 From f1f387c22dac8748a7edb1f4aa1ea6dac7dfbdfd Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 8 Mar 2018 15:23:35 +0100 Subject: ResourceAccessor: make it work with the modular renderer architecture This makes Scene2D work again. Tests restored as well. Change-Id: I4082d362c999a674be2debc297d59075f4b7c9e9 Reviewed-by: Paul Lemire --- tests/auto/render/commons/testrenderer.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/commons/testrenderer.h b/tests/auto/render/commons/testrenderer.h index 1241bb0e0..7b3e0a387 100644 --- a/tests/auto/render/commons/testrenderer.h +++ b/tests/auto/render/commons/testrenderer.h @@ -30,6 +30,7 @@ #define TESTRENDERER_H #include +#include QT_BEGIN_NAMESPACE @@ -42,11 +43,15 @@ public: void dumpInfo() const override {} API api() const override { return AbstractRenderer::OpenGL; } qint64 time() const override { return 0; } - void setTime(qint64 time) override { Q_UNUSED(time) } + void setTime(qint64 time) override { Q_UNUSED(time); } + void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override + { + m_managers = m; + m_resourceAccessor.reset(new Qt3DRender::Render::ResourceAccessor(this, m_managers)); + } + void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services); } + void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed); } void setJobsInLastFrame(int jobsInLastFrame) override { Q_UNUSED(jobsInLastFrame) } - void setNodeManagers(Qt3DRender::Render::NodeManagers *m) override { m_managers = m; } - void setServices(Qt3DCore::QServiceLocator *services) override { Q_UNUSED(services) } - void setSurfaceExposed(bool exposed) override { Q_UNUSED(exposed) } Qt3DRender::Render::NodeManagers *nodeManagers() const override { return m_managers; } Qt3DCore::QServiceLocator *services() const override { return nullptr; } void initialize() override {} @@ -87,12 +92,15 @@ public: QSurfaceFormat format() override; void setOpenGLContext(QOpenGLContext *) override {} + bool accessOpenGLTexture(Qt3DCore::QNodeId, QOpenGLTexture **, QMutex **, bool) override { return false; } + QSharedPointer resourceAccessor() const override { return m_resourceAccessor; } void loadShader(Qt3DRender::Render::Shader *, Qt3DRender::Render::HShader) override {} protected: Qt3DRender::Render::AbstractRenderer::BackendNodeDirtySet m_changes; Qt3DRender::Render::NodeManagers *m_managers = nullptr; + QSharedPointer m_resourceAccessor; }; QT_END_NAMESPACE -- cgit v1.2.3 From 0e115ff000fb294de8519bf5b39beee0d6bfa605 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 12 Mar 2018 08:32:35 +0100 Subject: Make the OpenGL renderer a plugin By default the QRenderAspect will try to load this plugin Change-Id: Ie55e207fb8e6d0b64f717bbb99699eb669eaa3f2 Task-number: QTBUG-61151 Reviewed-by: Mike Krus --- .../render/computecommand/tst_computecommand.cpp | 89 - tests/auto/render/effect/tst_effect.cpp | 1 - .../render/filtercompatibletechniquejob/BLACKLIST | 6 - .../filtercompatibletechniquejob.pro | 12 - .../tst_filtercompatibletechniquejob.cpp | 263 -- .../render/glshadermanager/glshadermanager.pro | 12 - .../render/glshadermanager/tst_glshadermanager.cpp | 199 -- .../render/graphicshelpergl2/graphicshelpergl2.pro | 13 - .../graphicshelpergl2/tst_graphicshelpergl2.cpp | 1605 ------------ .../graphicshelpergl3_2/graphicshelpergl3_2.pro | 13 - .../tst_graphicshelpergl3_2.cpp | 2294 ----------------- .../graphicshelpergl3_3/graphicshelpergl3_3.pro | 13 - .../tst_graphicshelpergl3_3.cpp | 2393 ------------------ .../render/graphicshelpergl4/graphicshelpergl4.pro | 13 - .../graphicshelpergl4/tst_graphicshelpergl4.cpp | 2583 -------------------- .../render/layerfiltering/tst_layerfiltering.cpp | 1 + .../materialparametergathererjob.pro | 11 - .../tst_materialparametergathererjob.cpp | 799 ------ .../opengl/computecommand/computecommand.pro | 15 + .../opengl/computecommand/tst_computecommand.cpp | 143 ++ .../opengl/filtercompatibletechniquejob/BLACKLIST | 6 + .../filtercompatibletechniquejob.pro | 15 + .../tst_filtercompatibletechniquejob.cpp | 263 ++ .../opengl/glshadermanager/glshadermanager.pro | 15 + .../opengl/glshadermanager/tst_glshadermanager.cpp | 199 ++ .../opengl/graphicshelpergl2/graphicshelpergl2.pro | 16 + .../graphicshelpergl2/tst_graphicshelpergl2.cpp | 1605 ++++++++++++ .../graphicshelpergl3_2/graphicshelpergl3_2.pro | 16 + .../tst_graphicshelpergl3_2.cpp | 2294 +++++++++++++++++ .../graphicshelpergl3_3/graphicshelpergl3_3.pro | 16 + .../tst_graphicshelpergl3_3.cpp | 2393 ++++++++++++++++++ .../opengl/graphicshelpergl4/graphicshelpergl4.pro | 16 + .../graphicshelpergl4/tst_graphicshelpergl4.cpp | 2583 ++++++++++++++++++++ .../materialparametergathererjob.pro | 14 + .../tst_materialparametergathererjob.cpp | 801 ++++++ tests/auto/render/opengl/opengl.pro | 19 + tests/auto/render/opengl/opengl_render_plugin.pri | 18 + .../opengl/qgraphicsutils/qgraphicsutils.pro | 12 + .../opengl/qgraphicsutils/tst_qgraphicsutils.cpp | 355 +++ tests/auto/render/opengl/renderer/renderer.pro | 12 + tests/auto/render/opengl/renderer/tst_renderer.cpp | 348 +++ .../auto/render/opengl/renderqueue/renderqueue.pro | 14 + .../render/opengl/renderqueue/tst_renderqueue.cpp | 243 ++ .../opengl/renderviewbuilder/renderviewbuilder.pro | 15 + .../renderviewbuilder/tst_renderviewbuilder.cpp | 669 +++++ .../auto/render/opengl/renderviews/renderviews.pro | 15 + .../render/opengl/renderviews/tst_renderviews.cpp | 554 +++++ .../opengl/renderviewutils/renderviewutils.pro | 15 + .../opengl/renderviewutils/tst_renderviewutils.cpp | 801 ++++++ tests/auto/render/opengl/textures/textures.pro | 15 + tests/auto/render/opengl/textures/tst_textures.cpp | 821 +++++++ .../tst_pickboundingvolumejob.cpp | 2 + .../proximityfiltering/tst_proximityfiltering.cpp | 4 + tests/auto/render/qcamera/tst_qcamera.cpp | 1 + .../auto/render/qgraphicsutils/qgraphicsutils.pro | 9 - .../render/qgraphicsutils/tst_qgraphicsutils.cpp | 355 --- .../render/raycastingjob/tst_raycastingjob.cpp | 1 + tests/auto/render/render.pro | 18 +- tests/auto/render/renderer/renderer.pro | 9 - tests/auto/render/renderer/tst_renderer.cpp | 349 --- tests/auto/render/renderqueue/renderqueue.pro | 11 - tests/auto/render/renderqueue/tst_renderqueue.cpp | 243 -- .../render/renderviewbuilder/renderviewbuilder.pro | 12 - .../renderviewbuilder/tst_renderviewbuilder.cpp | 669 ----- tests/auto/render/renderviews/renderviews.pro | 12 - tests/auto/render/renderviews/tst_renderviews.cpp | 552 ----- .../render/renderviewutils/renderviewutils.pro | 12 - .../render/renderviewutils/tst_renderviewutils.cpp | 800 ------ tests/auto/render/technique/tst_technique.cpp | 1 - tests/auto/render/textures/textures.pro | 12 - tests/auto/render/textures/tst_textures.cpp | 821 ------- .../trianglesextractor/tst_trianglesextractor.cpp | 1 - tests/benchmarks/render/jobs/jobs.pro | 4 + tests/benchmarks/render/jobs/tst_bench_jobs.cpp | 2 +- .../materialparametergathering.pro | 3 + .../tst_bench_materialparametergathering.cpp | 2 +- 76 files changed, 14356 insertions(+), 14205 deletions(-) delete mode 100644 tests/auto/render/filtercompatibletechniquejob/BLACKLIST delete mode 100644 tests/auto/render/filtercompatibletechniquejob/filtercompatibletechniquejob.pro delete mode 100644 tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp delete mode 100644 tests/auto/render/glshadermanager/glshadermanager.pro delete mode 100644 tests/auto/render/glshadermanager/tst_glshadermanager.cpp delete mode 100644 tests/auto/render/graphicshelpergl2/graphicshelpergl2.pro delete mode 100644 tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp delete mode 100644 tests/auto/render/graphicshelpergl3_2/graphicshelpergl3_2.pro delete mode 100644 tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp delete mode 100644 tests/auto/render/graphicshelpergl3_3/graphicshelpergl3_3.pro delete mode 100644 tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp delete mode 100644 tests/auto/render/graphicshelpergl4/graphicshelpergl4.pro delete mode 100644 tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp delete mode 100644 tests/auto/render/materialparametergathererjob/materialparametergathererjob.pro delete mode 100644 tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp create mode 100644 tests/auto/render/opengl/computecommand/computecommand.pro create mode 100644 tests/auto/render/opengl/computecommand/tst_computecommand.cpp create mode 100644 tests/auto/render/opengl/filtercompatibletechniquejob/BLACKLIST create mode 100644 tests/auto/render/opengl/filtercompatibletechniquejob/filtercompatibletechniquejob.pro create mode 100644 tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp create mode 100644 tests/auto/render/opengl/glshadermanager/glshadermanager.pro create mode 100644 tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp create mode 100644 tests/auto/render/opengl/graphicshelpergl2/graphicshelpergl2.pro create mode 100644 tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp create mode 100644 tests/auto/render/opengl/graphicshelpergl3_2/graphicshelpergl3_2.pro create mode 100644 tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp create mode 100644 tests/auto/render/opengl/graphicshelpergl3_3/graphicshelpergl3_3.pro create mode 100644 tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp create mode 100644 tests/auto/render/opengl/graphicshelpergl4/graphicshelpergl4.pro create mode 100644 tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp create mode 100644 tests/auto/render/opengl/materialparametergathererjob/materialparametergathererjob.pro create mode 100644 tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp create mode 100644 tests/auto/render/opengl/opengl.pro create mode 100644 tests/auto/render/opengl/opengl_render_plugin.pri create mode 100644 tests/auto/render/opengl/qgraphicsutils/qgraphicsutils.pro create mode 100644 tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp create mode 100644 tests/auto/render/opengl/renderer/renderer.pro create mode 100644 tests/auto/render/opengl/renderer/tst_renderer.cpp create mode 100644 tests/auto/render/opengl/renderqueue/renderqueue.pro create mode 100644 tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp create mode 100644 tests/auto/render/opengl/renderviewbuilder/renderviewbuilder.pro create mode 100644 tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp create mode 100644 tests/auto/render/opengl/renderviews/renderviews.pro create mode 100644 tests/auto/render/opengl/renderviews/tst_renderviews.cpp create mode 100644 tests/auto/render/opengl/renderviewutils/renderviewutils.pro create mode 100644 tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp create mode 100644 tests/auto/render/opengl/textures/textures.pro create mode 100644 tests/auto/render/opengl/textures/tst_textures.cpp delete mode 100644 tests/auto/render/qgraphicsutils/qgraphicsutils.pro delete mode 100644 tests/auto/render/qgraphicsutils/tst_qgraphicsutils.cpp delete mode 100644 tests/auto/render/renderer/renderer.pro delete mode 100644 tests/auto/render/renderer/tst_renderer.cpp delete mode 100644 tests/auto/render/renderqueue/renderqueue.pro delete mode 100644 tests/auto/render/renderqueue/tst_renderqueue.cpp delete mode 100644 tests/auto/render/renderviewbuilder/renderviewbuilder.pro delete mode 100644 tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp delete mode 100644 tests/auto/render/renderviews/renderviews.pro delete mode 100644 tests/auto/render/renderviews/tst_renderviews.cpp delete mode 100644 tests/auto/render/renderviewutils/renderviewutils.pro delete mode 100644 tests/auto/render/renderviewutils/tst_renderviewutils.cpp delete mode 100644 tests/auto/render/textures/textures.pro delete mode 100644 tests/auto/render/textures/tst_textures.cpp (limited to 'tests') diff --git a/tests/auto/render/computecommand/tst_computecommand.cpp b/tests/auto/render/computecommand/tst_computecommand.cpp index 4dc6b4436..d6fa1d579 100644 --- a/tests/auto/render/computecommand/tst_computecommand.cpp +++ b/tests/auto/render/computecommand/tst_computecommand.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,20 +42,6 @@ #include "testpostmanarbiter.h" -// tst_Renderer is a friend class of Renderer -class tst_Renderer : public Qt3DRender::Render::Renderer -{ -public: - tst_Renderer() - : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous) - {} - - ~tst_Renderer() { - shutdown(); - } -}; - - class tst_ComputeCommand : public Qt3DCore::QBackendNodeTester { Q_OBJECT @@ -271,80 +256,6 @@ private Q_SLOTS: QCOMPARE(backendComputeCommand.hasReachedFrameCount(), false); QCOMPARE(backendComputeCommand.frameCount(), 1); } - - void checkDisablesFrontend() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManager; - tst_Renderer renderer; - TestArbiter arbiter; - - Qt3DCore::QAspectManager manager; - Qt3DCore::QScene scene; - - Qt3DCore::QEntity rootEntity; - Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene); - - Qt3DRender::QComputeCommand computeCommand; - Qt3DRender::Render::ComputeCommand *backendComputeCommand = nullptr; - - renderer.setNodeManagers(&nodeManager); - - // WHEN - computeCommand.setParent(&rootEntity); - // RootEntity is the entry point to retrieve the scene instance for lookups - manager.setRootEntity(&rootEntity, {}); - - // THEN - QVERIFY(scene.lookupNode(computeCommand.id()) != nullptr); - - // WHEN - auto handle = nodeManager.computeJobManager()->getOrAcquireHandle(computeCommand.id()); - backendComputeCommand = nodeManager.computeJobManager()->data(handle); - - // WHEN - computeCommand.setWorkGroupX(256); - computeCommand.setWorkGroupY(512); - computeCommand.setWorkGroupZ(128); - computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual); - computeCommand.trigger(1); - - Qt3DCore::QBackendNodePrivate::get(backendComputeCommand)->setArbiter(&arbiter); - backendComputeCommand->setRenderer(&renderer); - simulateInitializationSync(&computeCommand, backendComputeCommand); - - // THEN - QCOMPARE(backendComputeCommand->frameCount(),1); - QCOMPARE(backendComputeCommand->isEnabled(), true); - QCOMPARE(computeCommand.isEnabled(), true); - QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); - - // WHEN - backendComputeCommand->updateFrameCount(); - - // THEN - QCOMPARE(backendComputeCommand->frameCount(), 0); - QCOMPARE(backendComputeCommand->hasReachedFrameCount(), true); - - - // Still enabled as we have yet to notify the fronted - QCOMPARE(backendComputeCommand->isEnabled(), true); - QCOMPARE(computeCommand.isEnabled(), true); - - // WHEN - renderer.jobsDone(&manager); // so Renderer::sendDisablesToFrontend gets called - - // THEN - QCOMPARE(computeCommand.isEnabled(), false); - QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); - - // WHEN - backendComputeCommand->syncFromFrontEnd(&computeCommand, false); - - // THEN - QCOMPARE(backendComputeCommand->frameCount(), 0); - QCOMPARE(backendComputeCommand->isEnabled(), false); - } }; QTEST_MAIN(tst_ComputeCommand) diff --git a/tests/auto/render/effect/tst_effect.cpp b/tests/auto/render/effect/tst_effect.cpp index 369cdf793..2b145669e 100644 --- a/tests/auto/render/effect/tst_effect.cpp +++ b/tests/auto/render/effect/tst_effect.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include "qbackendnodetester.h" #include "testrenderer.h" diff --git a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/filtercompatibletechniquejob/BLACKLIST deleted file mode 100644 index 7cbc7c4c0..000000000 --- a/tests/auto/render/filtercompatibletechniquejob/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -#[checkRunRendererRunning] -windows-7 -windows-7sp1 -#QTBUG-64271 -# Offscreen platform does not support OpenGL context creation -b2qt diff --git a/tests/auto/render/filtercompatibletechniquejob/filtercompatibletechniquejob.pro b/tests/auto/render/filtercompatibletechniquejob/filtercompatibletechniquejob.pro deleted file mode 100644 index 4f63e514b..000000000 --- a/tests/auto/render/filtercompatibletechniquejob/filtercompatibletechniquejob.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_filtercompatibletechniquejob - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_filtercompatibletechniquejob.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp deleted file mode 100644 index 618709269..000000000 --- a/tests/auto/render/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class TestAspect : public Qt3DRender::QRenderAspect -{ -public: - TestAspect(Qt3DCore::QNode *root) - : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) - , m_jobManager(new Qt3DCore::QAspectJobManager()) - , m_window(new QWindow()) - , m_contextCreationSuccessful(false) - { - m_window->setSurfaceType(QWindow::OpenGLSurface); - m_window->setGeometry(0, 0, 10, 10); - m_window->create(); - - if (!m_glContext.create()) { - qWarning() << "Failed to create OpenGL context"; - return; - } - - if (!m_glContext.makeCurrent(m_window.data())) { - qWarning() << "Failed to make OpenGL context current"; - return; - } - - m_contextCreationSuccessful = true; - - Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); - QRenderAspect::onRegistered(); - - QVector nodes; - Qt3DCore::QNodeVisitor v; - v.traverse(root, [&nodes](Qt3DCore::QNode *node) { - Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); - d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); - d->m_hasBackendNode = true; - nodes << node; - }); - - for (const auto node: nodes) - d_func()->createBackendNode({ - node->id(), - Qt3DCore::QNodePrivate::get(node)->m_typeInfo, - Qt3DCore::NodeTreeChange::Added, - node - }); - } - - ~TestAspect() - { - if (m_contextCreationSuccessful) - QRenderAspect::onUnregistered(); - } - - Qt3DRender::Render::NodeManagers *nodeManagers() const - { - return d_func()->m_renderer - ? d_func()->m_renderer->nodeManagers() : nullptr; - } - - bool contextCreationSuccessful() const - { - return m_contextCreationSuccessful; - } - - void initializeRenderer() - { - renderer()->setOpenGLContext(&m_glContext); - d_func()->m_renderer->initialize(); - renderer()->submissionContext()->beginDrawing(m_window.data()); - } - - Render::Renderer *renderer() const - { - return static_cast(d_func()->m_renderer); - } - - void onRegistered() { QRenderAspect::onRegistered(); } - void onUnregistered() { QRenderAspect::onUnregistered(); } - -private: - QScopedPointer m_jobManager; - QScopedPointer m_window; - QOpenGLContext m_glContext; - bool m_contextCreationSuccessful; -}; - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -namespace { - -Qt3DCore::QEntity *buildTestScene() -{ - Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); - - // FrameGraph - Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); - renderSettings->setActiveFrameGraph(new Qt3DRender::QViewport()); - root->addComponent(renderSettings); - - // Scene - Qt3DRender::QTechnique *gl2Technique = new Qt3DRender::QTechnique(root); - gl2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); - gl2Technique->graphicsApiFilter()->setMajorVersion(2); - gl2Technique->graphicsApiFilter()->setMinorVersion(0); - gl2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); - - Qt3DRender::QTechnique *gl3Technique = new Qt3DRender::QTechnique(root); - gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); - gl3Technique->graphicsApiFilter()->setMajorVersion(3); - gl3Technique->graphicsApiFilter()->setMinorVersion(2); - gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); - - Qt3DRender::QTechnique *es2Technique = new Qt3DRender::QTechnique(root); - es2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES); - es2Technique->graphicsApiFilter()->setMajorVersion(2); - es2Technique->graphicsApiFilter()->setMinorVersion(0); - es2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); - - return root; -} - -} // anonymous - -class tst_FilterCompatibleTechniqueJob : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - - void initTestCase() - { - QSurfaceFormat format; -#ifdef QT_OPENGL_ES_2 - format.setRenderableType(QSurfaceFormat::OpenGLES); -#else - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { - format.setVersion(4, 3); - format.setProfile(QSurfaceFormat::CoreProfile); - } -#endif - format.setDepthBufferSize(24); - format.setSamples(4); - format.setStencilBufferSize(8); - QSurfaceFormat::setDefaultFormat(format); - } - - void checkInitialState() - { - // GIVEN - Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; - - // THEN - QVERIFY(backendFilterCompatibleTechniqueJob.manager() == nullptr); - QVERIFY(backendFilterCompatibleTechniqueJob.renderer() == nullptr); - - // WHEN - Qt3DRender::Render::TechniqueManager techniqueManager; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - backendFilterCompatibleTechniqueJob.setManager(&techniqueManager); - backendFilterCompatibleTechniqueJob.setRenderer(&renderer); - - // THEN - QCOMPARE(backendFilterCompatibleTechniqueJob.manager(), &techniqueManager); - QCOMPARE(backendFilterCompatibleTechniqueJob.renderer(), &renderer); - - renderer.shutdown(); - } - - void checkRunRendererRunning() - { - // GIVEN - Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; - Qt3DRender::TestAspect testAspect(buildTestScene()); - - const bool unableToCreateContext = !testAspect.contextCreationSuccessful(); - - if (unableToCreateContext) - QSKIP("Initialization failed, unable to create GL context"); - - // WHEN - Qt3DRender::Render::NodeManagers *nodeManagers = testAspect.nodeManagers(); - QVERIFY(nodeManagers); - Qt3DRender::Render::TechniqueManager *techniqueManager = nodeManagers->techniqueManager(); - QVERIFY(techniqueManager); - backendFilterCompatibleTechniqueJob.setManager(techniqueManager); - backendFilterCompatibleTechniqueJob.setRenderer(testAspect.renderer()); - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.renderer()->isRunning(), true); - QCOMPARE(testAspect.renderer()->submissionContext()->isInitialized(), true); - const QVector handles = testAspect.nodeManagers()->techniqueManager()->activeHandles(); - QCOMPARE(handles.size(), 3); - - // WHEN - backendFilterCompatibleTechniqueJob.run(); - - // THEN -> empty if job ran properly - const QVector dirtyTechniquesId = testAspect.nodeManagers()->techniqueManager()->takeDirtyTechniques(); - QCOMPARE(dirtyTechniquesId.size(), 0); - - // Check at least one technique is valid - bool foundValid = false; - for (const auto handle: handles) { - Qt3DRender::Render::Technique *technique = testAspect.nodeManagers()->techniqueManager()->data(handle); - foundValid |= technique->isCompatibleWithRenderer(); - } - QCOMPARE(foundValid, true); - } -}; - -QTEST_MAIN(tst_FilterCompatibleTechniqueJob) - -#include "tst_filtercompatibletechniquejob.moc" diff --git a/tests/auto/render/glshadermanager/glshadermanager.pro b/tests/auto/render/glshadermanager/glshadermanager.pro deleted file mode 100644 index 27aadf84f..000000000 --- a/tests/auto/render/glshadermanager/glshadermanager.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_glshadermanager - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_glshadermanager.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/glshadermanager/tst_glshadermanager.cpp b/tests/auto/render/glshadermanager/tst_glshadermanager.cpp deleted file mode 100644 index c18fb4793..000000000 --- a/tests/auto/render/glshadermanager/tst_glshadermanager.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include "qbackendnodetester.h" -#include "testrenderer.h" - -class tst_GLShaderManager : public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT - -private Q_SLOTS: - void adopt(); - void lookupResource(); - void abandon(); - void insertAfterRemoval(); -}; - -void tst_GLShaderManager::adopt() -{ - // GIVEN - Qt3DRender::Render::GLShaderManager cache; - Qt3DRender::QShaderProgram frontendShader1; - Qt3DRender::QShaderProgram frontendShader2; - TestRenderer renderer; - Qt3DRender::Render::Shader backendShaderNode1; - Qt3DRender::Render::Shader backendShaderNode2; - - backendShaderNode1.setRenderer(&renderer); - backendShaderNode2.setRenderer(&renderer); - simulateInitialization(&frontendShader1, &backendShaderNode1); - simulateInitialization(&frontendShader2, &backendShaderNode2); - - // THEN - QVERIFY(cache.lookupResource(backendShaderNode1.peerId()) == nullptr); - QVERIFY(cache.lookupResource(backendShaderNode2.peerId()) == nullptr); - QVERIFY(backendShaderNode1.peerId() != backendShaderNode2.peerId()); - - // WHEN - Qt3DRender::Render::GLShader *glShader1 = cache.createOrAdoptExisting(&backendShaderNode1); - - // THEN - QVERIFY(glShader1 != nullptr); - QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); - QCOMPARE(shaderNodeIds.size(), 1); - QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); - - // WHEN - Qt3DRender::Render::GLShader *glShader2 = cache.createOrAdoptExisting(&backendShaderNode2); - - // THEN - QCOMPARE(glShader1, glShader2); - - shaderNodeIds = cache.shaderIdsForProgram(glShader2); - QCOMPARE(shaderNodeIds.size(), 2); - QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); - QCOMPARE(shaderNodeIds.last(), backendShaderNode2.peerId()); -} - -void tst_GLShaderManager::lookupResource() -{ - // GIVEN - Qt3DRender::Render::GLShaderManager cache; - Qt3DRender::QShaderProgram frontendShader1; - Qt3DRender::QShaderProgram frontendShader2; - TestRenderer renderer; - Qt3DRender::Render::Shader backendShaderNode1; - Qt3DRender::Render::Shader backendShaderNode2; - - backendShaderNode1.setRenderer(&renderer); - backendShaderNode2.setRenderer(&renderer); - simulateInitialization(&frontendShader1, &backendShaderNode1); - simulateInitialization(&frontendShader2, &backendShaderNode2); - - // WHEN - cache.createOrAdoptExisting(&backendShaderNode1); - cache.createOrAdoptExisting(&backendShaderNode2); - - // THEN - Qt3DRender::Render::GLShader *glShader1 = cache.lookupResource(backendShaderNode1.peerId()); - Qt3DRender::Render::GLShader *glShader2 = cache.lookupResource(backendShaderNode2.peerId()); - QVERIFY(glShader1 != nullptr); - QCOMPARE(glShader1, glShader2); - const QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); - QCOMPARE(shaderNodeIds.size(), 2); - QVERIFY(shaderNodeIds.contains(frontendShader1.id())); - QVERIFY(shaderNodeIds.contains(frontendShader2.id())); -} - -void tst_GLShaderManager::abandon() -{ - // GIVEN - Qt3DRender::Render::GLShaderManager cache; - Qt3DRender::QShaderProgram frontendShader1; - Qt3DRender::QShaderProgram frontendShader2; - TestRenderer renderer; - Qt3DRender::Render::Shader backendShaderNode1; - Qt3DRender::Render::Shader backendShaderNode2; - - backendShaderNode1.setRenderer(&renderer); - backendShaderNode2.setRenderer(&renderer); - simulateInitialization(&frontendShader1, &backendShaderNode1); - simulateInitialization(&frontendShader2, &backendShaderNode2); - cache.createOrAdoptExisting(&backendShaderNode1); - cache.createOrAdoptExisting(&backendShaderNode2); - - // WHEN - Qt3DRender::Render::GLShader *glShader = cache.lookupResource(backendShaderNode1.peerId()); - cache.abandon(glShader, &backendShaderNode1); - - // THEN - QVector shaderNodeIds = cache.shaderIdsForProgram(glShader); - QVERIFY(cache.takeAbandonned().isEmpty()); - QCOMPARE(shaderNodeIds.size(), 1); - QCOMPARE(shaderNodeIds.first(), backendShaderNode2.peerId()); - - // WHEN - cache.abandon(glShader, &backendShaderNode2); - - // THEN - shaderNodeIds = cache.shaderIdsForProgram(glShader); - QCOMPARE(shaderNodeIds.size(), 0); - const QVector releasedShaders = cache.takeAbandonned(); - QCOMPARE(releasedShaders.size(), 1); - QCOMPARE(releasedShaders.first(), glShader); -} - -void tst_GLShaderManager::insertAfterRemoval() -{ - // GIVEN - Qt3DRender::Render::GLShaderManager cache; - Qt3DRender::QShaderProgram frontendShader; - TestRenderer renderer; - Qt3DRender::Render::Shader backendShaderNode; - - - backendShaderNode.setRenderer(&renderer); - simulateInitialization(&frontendShader, &backendShaderNode); - - // WHEN - Qt3DRender::Render::GLShader *apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); - const Qt3DRender::Render::GLShader *originalApiShader = apiShader1; - - // THEN - auto apiShader2 = cache.lookupResource(frontendShader.id()); - QVERIFY(apiShader1 != nullptr); - QVERIFY(apiShader2 != nullptr); - QVERIFY(apiShader1 == originalApiShader); - QVERIFY(apiShader1 == apiShader2); - - // WHEN - cache.abandon(apiShader1, &backendShaderNode); - - // THEN - Qt3DRender::Render::GLShader *apiShaderEmpty = cache.lookupResource(frontendShader.id()); - QVERIFY(apiShaderEmpty == nullptr); - - // WHEN - apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); - cache.purge(); - apiShader2 = cache.lookupResource(frontendShader.id()); - - // THEN - QVERIFY(apiShader1 != nullptr); - QVERIFY(apiShader2 != nullptr); - QVERIFY(apiShader1 == apiShader2); - QVERIFY(apiShader2 == originalApiShader); -} - -QTEST_APPLESS_MAIN(tst_GLShaderManager) - -#include "tst_glshadermanager.moc" diff --git a/tests/auto/render/graphicshelpergl2/graphicshelpergl2.pro b/tests/auto/render/graphicshelpergl2/graphicshelpergl2.pro deleted file mode 100644 index b27060635..000000000 --- a/tests/auto/render/graphicshelpergl2/graphicshelpergl2.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE = app - -TARGET = tst_graphicshelpergl2 - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib openglextensions - -CONFIG += testcase - -SOURCES += \ - tst_graphicshelpergl2.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp deleted file mode 100644 index ffafc2312..000000000 --- a/tests/auto/render/graphicshelpergl2/tst_graphicshelpergl2.cpp +++ /dev/null @@ -1,1605 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef QT_OPENGL_ES_2 - -#define TEST_SHOULD_BE_PERFORMED 1 - -QT_BEGIN_NAMESPACE - -using namespace Qt3DRender; -using namespace Qt3DRender::Render; - -namespace { - -const QByteArray vertCode = QByteArrayLiteral( - "#version 120\n" \ - "attribute vec3 vertexPosition;\n" \ - "attribute vec2 vertexTexCoord;\n" \ - "varying vec2 texCoord;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( - "#version 120\n" \ - "uniform float multiplier;\n" \ - "uniform vec2 multiplierVec2;\n" \ - "uniform vec3 multiplierVec3;\n" \ - "uniform vec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ - " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsInt = QByteArrayLiteral( - "#version 120\n" \ - "uniform int multiplier;\n" \ - "uniform ivec2 multiplierVec2;\n" \ - "uniform ivec3 multiplierVec3;\n" \ - "uniform ivec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ - " gl_FragColor = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( - "#version 120\n" \ - "uniform mat2 m2;\n" \ - "uniform mat2x3 m23;\n" \ - "uniform mat3x2 m32;\n" \ - "uniform mat2x4 m24;\n" \ - "uniform mat4x2 m42;\n" \ - "uniform mat3 m3;\n" \ - "uniform mat3x4 m34;\n" \ - "uniform mat4x3 m43;\n" \ - "uniform mat4 m4;\n" \ - "void main()\n" \ - "{\n" \ - " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ - " gl_FragColor = vec4(1, 0, 0, 1) * lengthSum;\n" \ - "}\n"); - - -const QByteArray fragCodeSamplers = QByteArrayLiteral( - "#version 120\n" \ - "varying vec2 texCoord;\n" \ - "uniform sampler1D s1;\n" \ - "uniform sampler2D s2;\n" \ - "uniform sampler3D s3;\n" \ - "uniform samplerCube scube;\n" \ - "void main()\n" \ - "{\n" \ - " gl_FragColor = vec4(1, 0, 0, 1) *" \ - " texture1D(s1, texCoord.x) *" \ - " texture2D(s2, texCoord) *" \ - " texture3D(s3, vec3(texCoord, 0.0)) *" \ - " textureCube(scube, vec3(texCoord, 0));\n" \ - "}\n"); - -} // anonymous - -class tst_GraphicsHelperGL2 : public QObject -{ - Q_OBJECT -private Q_SLOTS: - - void init() - { - m_window.reset(new QWindow); - m_window->setSurfaceType(QWindow::OpenGLSurface); - m_window->setGeometry(0, 0, 10, 10); - m_window->create(); - - QSurfaceFormat format; - format.setVersion(2, 0); - format.setProfile(QSurfaceFormat::NoProfile); - format.setDepthBufferSize(24); - format.setSamples(4); - format.setStencilBufferSize(8); - m_window->setFormat(format); - m_glContext.setFormat(format); - - if (!m_glContext.create()) { - qWarning() << "Failed to create OpenGL context"; - return; - } - - if (!m_glContext.makeCurrent(m_window.data())) { - qWarning() << "Failed to make OpenGL context current"; - return; - } - - if ((m_func = m_glContext.versionFunctions()) != nullptr) { - if (m_glContext.hasExtension(QByteArrayLiteral("GL_ARB_framebuffer_object"))) { - m_fboFuncs = new QOpenGLExtension_ARB_framebuffer_object(); - m_fboFuncs->initializeOpenGLFunctions(); - } - m_glHelper.initializeHelper(&m_glContext, m_func); - m_initializationSuccessful = true; - } - } - - void cleanup() - { - m_glContext.doneCurrent(); - } - - void alphaTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Deprecated - } - - void bindBufferBase() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // Not supported by GL2 - } - - void bindFragDataLocation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void bindFrameBufferAttachment() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA32F); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureAttachmentId = 0; - m_fboFuncs->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &textureAttachmentId); - QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); - - // Restore state - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - } - - void bindFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - - // THEN - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundindFBOId = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // Cleanup - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - } - - void bindShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void bindUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void blendEquation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - GLint equation = 0; - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_ADD); - - // WHEN - m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); - - // THEN - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); - } - - void blendFunci() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void blendFuncSeparatei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void boundFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - // WHEN - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - // THEN - GLint boundBuffer = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); - QCOMPARE(GLuint(boundBuffer), fboId); - - // THEN - QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); - - // Reset state - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - } - - void checkFrameBufferComplete() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - QVERIFY(m_glHelper.checkFrameBufferComplete()); - - // Restore - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - } - - void clearBufferf() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void createFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // WHEN - const GLuint fboId = m_glHelper.createFrameBufferObject(); - - // THEN - QVERIFY(fboId != 0); - - // Restore - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - } - - void depthMask() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - GLboolean depthWritingEnabled = false; - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - - // THEN - QVERIFY(depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_FALSE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(!depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_TRUE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(depthWritingEnabled); - } - - void depthTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glDisable(GL_DEPTH_TEST); - m_func->glDepthFunc(GL_LESS); - - // WHEN - m_glHelper.depthTest(GL_LEQUAL); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - GLint depthMode = 0; - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LEQUAL); - - // WHEN - m_glHelper.depthTest(GL_LESS); - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LESS); - } - - void disableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glEnable(GL_CLIP_DISTANCE0 + 5); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - - // WHEN - m_glHelper.disableClipPlane(5); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - } - - void disablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void disablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void drawBuffers() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - QOpenGLTexture *textures[4]; - - // Create 4 attachments - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - // THEN - GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // WHEN - GLenum bufferEnum = GL_COLOR_ATTACHMENT4; - m_func->glDrawBuffers(1, &bufferEnum); - - // THEN - GLint enumValue = -1; - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); - - // WHEN - GLint newBufferEnum = 2; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // WHEN - newBufferEnum = 0; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // Restore - m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_fboFuncs->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void enableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glDisable(GL_CLIP_DISTANCE0 + 4); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - - // WHEN - m_glHelper.enableClipPlane(4); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - } - - void enablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void enablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void enableVertexAttribute() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - shaderProgram.bind(); - - // WHEN - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void frontFace() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glFrontFace(GL_CW); - - // THEN - GLint face = 0; - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CW); - - // WHEN - m_glHelper.frontFace(GL_CCW); - - // THEN - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CCW); - } - - void getRenderBufferDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void getTextureDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - - // WHEN - const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - } - - void pointSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // WHEN - m_glHelper.pointSize(false, 0.5f); - // THEN - GLfloat size = 0.0f; - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 0.5f); - } - - void maxClipPlaneCount() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - GLint maxCount = -1; - m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); - - // THEN - QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); - } - - void programUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // Not supported by GL2 - } - - void programAttributesAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeAttributes.size(), 2); - std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); - - const ShaderAttribute attribute1 = activeAttributes.at(0); - QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); - QCOMPARE(attribute1.m_size, 1); - QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); - QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); - - const ShaderAttribute attribute2 = activeAttributes.at(1); - QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); - QCOMPARE(attribute2.m_size, 1); - QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); - QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); - } - - void programUniformsAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniforms.size(), 4); - std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); - - const ShaderUniform uniform1 = activeUniforms.at(0); - QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); - QCOMPARE(uniform1.m_offset, -1); - QCOMPARE(uniform1.m_blockIndex, -1); - QCOMPARE(uniform1.m_arrayStride, -1); - QCOMPARE(uniform1.m_matrixStride, -1); - QCOMPARE(uniform1.m_size, 1); - QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); - QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); - - const ShaderUniform uniform2 = activeUniforms.at(1); - QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); - QCOMPARE(uniform2.m_offset, -1); - QCOMPARE(uniform2.m_blockIndex, -1); - QCOMPARE(uniform2.m_arrayStride, -1); - QCOMPARE(uniform2.m_matrixStride, -1); - QCOMPARE(uniform2.m_size, 1); - QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); - QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); - - const ShaderUniform uniform3 = activeUniforms.at(2); - QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); - QCOMPARE(uniform3.m_offset, -1); - QCOMPARE(uniform3.m_blockIndex, -1); - QCOMPARE(uniform3.m_arrayStride, -1); - QCOMPARE(uniform3.m_matrixStride, -1); - QCOMPARE(uniform3.m_size, 1); - QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); - QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); - - const ShaderUniform uniform4 = activeUniforms.at(3); - QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); - QCOMPARE(uniform4.m_offset, -1); - QCOMPARE(uniform4.m_blockIndex, -1); - QCOMPARE(uniform4.m_arrayStride, -1); - QCOMPARE(uniform4.m_matrixStride, -1); - QCOMPARE(uniform4.m_size, 1); - QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); - QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); - } - - void programShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void releaseFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - if (!m_fboFuncs) - QSKIP("FBO not supported by OpenGL 2.0"); - // GIVEN - GLuint fboId; - m_fboFuncs->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.releaseFrameBufferObject(fboId); - - // THEN - QVERIFY(!m_fboFuncs->glIsFramebuffer(fboId)); - } - - void setMSAAEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glDisable(GL_MULTISAMPLE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - } - - void setAlphaCoverageEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - } - - void setClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // Deprecated in 3.3 core - } - - void setSeamlessCubemap() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported in GL2 - } - - void setVerticesPerPatch() - { - // Not supported in GL2 - } - -#define SUPPORTS_FEATURE(Feature, IsSupported) \ - QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); - - void supportsFeature() - { - SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, (m_fboFuncs != nullptr)); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::Tessellation, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::IndirectDrawing, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::MapBuffer, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::Fences, false); - } - - -#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ - QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; - - void uniformsByteSize_data() - { - QTest::addColumn("fragShader"); - QTest::addColumn("name"); - QTest::addColumn("type"); - QTest::addColumn("componentSize"); - QTest::addColumn("expectedByteSize"); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); - } - - void uniformsByteSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QFETCH(QByteArray, fragShader); - QFETCH(QString, name); - QFETCH(int, type); - QFETCH(int, componentSize); - QFETCH(int, expectedByteSize); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); - QVERIFY(shaderProgram.link()); - - GLint location = shaderProgram.uniformLocation(name); - // WHEN - const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - ShaderUniform matchingUniform; - for (const ShaderUniform &u : activeUniforms) { - if (u.m_location == location) { - matchingUniform = u; - break; - } - } - - // THEN - QCOMPARE(matchingUniform.m_location, location); - QCOMPARE(matchingUniform.m_type, GLuint(type)); - QCOMPARE(matchingUniform.m_size, componentSize); - - // WHEN - const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); - - // THEN - QCOMPARE(expectedByteSize, computedRawByteSize); - - // Restore - m_func->glUseProgram(0); - } - - void useProgram() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - - // THEN - QVERIFY(shaderProgram.link()); - - GLint currentProg = 0; - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - - // WHEN - m_glHelper.useProgram(shaderProgram.programId()); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QCOMPARE(GLuint(currentProg), shaderProgram.programId()); - - // WHEN - m_glHelper.useProgram(0); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - } - - void vertexAttribDivisor() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not available in 3.2 - } - - void vertexAttributePointer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - - const int vertexCount = 99; - QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); - positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - positionBuffer.create(); - positionBuffer.bind(); - positionBuffer.allocate(vertexCount * sizeof(QVector3D)); - - QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); - texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - texCoordBuffer.create(); - texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); - - // WHEN - shaderProgram.bind(); - positionBuffer.bind(); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); - - texCoordBuffer.bind(); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void glUniform1fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat value = 883.0f; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1fv(location, 1, &value); - - // THEN - GLfloat setValue = 0.0f; - m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[2] = { 383.0f, 427.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2fv(location, 1, values); - - // THEN - GLfloat setValues[2] = { 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3fv(location, 1, values); - - // THEN - GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint value = 883; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1iv(location, 1, &value); - - // THEN - GLint setValue = 0; - m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[2] = { 383, 427 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2iv(location, 1, values); - - // THEN - GLint setValues[2] = { 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[3] = { 572, 1340, 1584 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3iv(location, 1, values); - - // THEN - GLint setValues[3] = { 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[4] = { 454, 350, 883, 355 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4iv(location, 1, values); - - // THEN - GLint setValues[4] = { 0, 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniform2uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniform3uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniform4uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("m2"); - m_glHelper.glUniformMatrix2fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; - const GLint location = shaderProgram.uniformLocation("m3"); - m_glHelper.glUniformMatrix3fv(location, 1, values); - - // THEN - GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 9; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; - const GLint location = shaderProgram.uniformLocation("m4"); - m_glHelper.glUniformMatrix4fv(location, 1, values); - - // THEN - GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 16; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix3x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix2x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix4x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix3x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void glUniformMatrix4x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void blitFramebuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - -#define ADD_GL_TYPE_ENTRY(Type, Expected) \ - QTest::newRow(#Type) << Type << Expected; - - void uniformTypeFromGLType_data() - { - QTest::addColumn("glType"); - QTest::addColumn("expected"); - - ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); - ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); - ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); - ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); - ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); - } - - void uniformTypeFromGLType() - { - // GIVEN - QFETCH(int, glType); - QFETCH(UniformType, expected); - - // WHEN - UniformType computed = m_glHelper.uniformTypeFromGLType(glType); - - // THEN - QCOMPARE(computed, expected); - } - - void drawBuffer() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void readBuffer() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void fenceSync() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void clientWaitSync() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void waitSync() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void wasSyncSignaled() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void deleteSync() - { - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - // Not supported by GL2 - } - - void rasterMode() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_POLYGON_MODE, &p); - QCOMPARE(p, GL_LINE); - } - -private: - QScopedPointer m_window; - QOpenGLContext m_glContext; - GraphicsHelperGL2 m_glHelper; - QOpenGLFunctions_2_0 *m_func = nullptr; - QOpenGLExtension_ARB_framebuffer_object *m_fboFuncs = nullptr; - bool m_initializationSuccessful = false; -}; - -QT_END_NAMESPACE - -#endif - -int main(int argc, char *argv[]) -{ -#ifdef TEST_SHOULD_BE_PERFORMED - QGuiApplication app(argc, argv); - app.setAttribute(Qt::AA_Use96Dpi, true); - tst_GraphicsHelperGL2 tc; - QTEST_SET_MAIN_SOURCE_PATH - return QTest::qExec(&tc, argc, argv); -#endif - return 0; -} - -#ifdef TEST_SHOULD_BE_PERFORMED -#include "tst_graphicshelpergl2.moc" -#endif diff --git a/tests/auto/render/graphicshelpergl3_2/graphicshelpergl3_2.pro b/tests/auto/render/graphicshelpergl3_2/graphicshelpergl3_2.pro deleted file mode 100644 index 5d8bf60fd..000000000 --- a/tests/auto/render/graphicshelpergl3_2/graphicshelpergl3_2.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE = app - -TARGET = tst_graphicshelpergl3_2 - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += \ - tst_graphicshelpergl3_2.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp deleted file mode 100644 index 840a7f6da..000000000 --- a/tests/auto/render/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp +++ /dev/null @@ -1,2294 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) - -#define TEST_SHOULD_BE_PERFORMED 1 - -using namespace Qt3DRender; -using namespace Qt3DRender::Render; - -namespace { - -const QByteArray vertCode = QByteArrayLiteral( - "#version 150 core\n" \ - "in vec3 vertexPosition;\n" \ - "in vec2 vertexTexCoord;\n" \ - "out vec2 texCoord;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( - "#version 150 core\n" \ - "in vec3 vertexPosition;\n" \ - "in vec2 vertexTexCoord;\n" \ - "in int vertexColorIndex;\n" \ - "out vec2 texCoord;\n" \ - "flat out int colorIndex;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " colorIndex = vertexColorIndex;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeFragOutputs = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "out vec2 temp;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ - " temp = vec2(1.0, 0.3);\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "uniform float multiplier;\n" \ - "uniform vec2 multiplierVec2;\n" \ - "uniform vec3 multiplierVec3;\n" \ - "uniform vec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsInt = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "uniform int multiplier;\n" \ - "uniform ivec2 multiplierVec2;\n" \ - "uniform ivec3 multiplierVec3;\n" \ - "uniform ivec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ - " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "uniform uint multiplier;\n" \ - "uniform uvec2 multiplierVec2;\n" \ - "uniform uvec3 multiplierVec3;\n" \ - "uniform uvec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ - " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "uniform mat2 m2;\n" \ - "uniform mat2x3 m23;\n" \ - "uniform mat3x2 m32;\n" \ - "uniform mat2x4 m24;\n" \ - "uniform mat4x2 m42;\n" \ - "uniform mat3 m3;\n" \ - "uniform mat3x4 m34;\n" \ - "uniform mat4x3 m43;\n" \ - "uniform mat4 m4;\n" \ - "void main()\n" \ - "{\n" \ - " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ - " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ - "}\n"); - -const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( - "#version 150 core\n" \ - "out vec4 color;\n" \ - "in vec2 texCoord;\n" \ - "flat in int colorIndex;\n" \ - "uniform ColorArray\n" \ - "{\n" \ - " vec4 colors[256];\n" \ - "};\n" \ - "void main()\n" \ - "{\n" \ - " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeSamplers = QByteArrayLiteral( - "#version 150 core\n" \ - "in vec2 texCoord;\n" \ - "out vec4 color;\n" \ - "uniform sampler1D s1;\n" \ - "uniform sampler2D s2;\n" \ - "uniform sampler2DArray s2a;\n" \ - "uniform sampler3D s3;\n" \ - "uniform samplerCube scube;\n" \ - "uniform sampler2DRect srect;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1, 0, 0, 1) *" \ - " texture(s1, texCoord.x) *" \ - " texture(s2, texCoord) *" \ - " texture(s2a, vec3(texCoord, 0.0)) *" \ - " texture(s3, vec3(texCoord, 0.0)) *" \ - " texture(scube, vec3(texCoord, 0)) *" \ - " texture(srect, texCoord);\n" \ - "}\n"); - -} // anonymous - -class tst_GraphicsHelperGL3_2 : public QObject -{ - Q_OBJECT -private Q_SLOTS: - - void init() - { - m_window.reset(new QWindow); - m_window->setSurfaceType(QWindow::OpenGLSurface); - m_window->setGeometry(0, 0, 10, 10); - m_window->create(); - - QSurfaceFormat format; - format.setVersion(3, 2); - format.setProfile(QSurfaceFormat::CoreProfile); - format.setDepthBufferSize(24); - format.setSamples(4); - format.setStencilBufferSize(8); - m_window->setFormat(format); - m_glContext.setFormat(format); - - if (!m_glContext.create()) { - qWarning() << "Failed to create OpenGL context"; - return; - } - - if (!m_glContext.makeCurrent(m_window.data())) { - qWarning() << "Failed to make OpenGL context current"; - return; - } - - if ((m_func = m_glContext.versionFunctions()) != nullptr) { - m_glHelper.initializeHelper(&m_glContext, m_func); - m_initializationSuccessful = true; - } - } - - void cleanup() - { - m_glContext.doneCurrent(); - } - - void alphaTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - // Deprecated - } - - void bindBufferBase() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint bufferId = 0; - // WHEN - m_func->glGenBuffers(1, &bufferId); - // THEN - QVERIFY(bufferId != 0); - - - // WHEN - m_func->glBindBuffer(GL_UNIFORM_BUFFER, bufferId); - m_glHelper.bindBufferBase(GL_UNIFORM_BUFFER, 2, bufferId); - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundToPointBufferId = 0; - m_func->glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, 2, &boundToPointBufferId); - QVERIFY(boundToPointBufferId == GLint(bufferId)); - - // Restore to sane state - m_func->glBindBuffer(GL_UNIFORM_BUFFER, 0); - m_func->glDeleteBuffers(1, &bufferId); - } - - void bindFragDataLocation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // WHEN - QHash fragLocations; - fragLocations.insert(QStringLiteral("temp"), 2); - fragLocations.insert(QStringLiteral("color"), 1); - m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); - - // THEN - QVERIFY(shaderProgram.link()); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); - const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); - QCOMPARE(tempLocation, 2); - QCOMPARE(colorLocation, 1); - } - - void bindFrameBufferAttachment() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA32F); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureAttachmentId = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &textureAttachmentId); - QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void bindFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - - // THEN - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundindFBOId = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // Cleanup - m_func->glDeleteFramebuffers(1, &fboId); - } - - void bindShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - // Not supported in OpenGL 3.2 - } - - void bindUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); - m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void blendEquation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLint equation = 0; - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_ADD); - - // WHEN - m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); - - // THEN - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); - } - - void blendFunci() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - // Not supported by OpenGL 3.2 - } - - void blendFuncSeparatei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // Not supported by OpenGL 3.2 - } - - void boundFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - // THEN - GLint boundBuffer = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); - QCOMPARE(GLuint(boundBuffer), fboId); - - // THEN - QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); - - // Reset state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void checkFrameBufferComplete() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - QVERIFY(m_glHelper.checkFrameBufferComplete()); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void clearBufferf() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - // Create 4 attachments - QOpenGLTexture *textures[4]; - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // Set Draw buffers - GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; - m_func->glDrawBuffers(1, &clearBufferEnum); - - const GLint bufferIndex = 0; // index of the element in the draw buffers - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // WHEN - const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); - m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); - error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - QVector colors(512 * 512); - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - for (const QVector4D c : colors) { - QVERIFY(c == clearValue1); - } - - // WHEN - const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); - m_glHelper.clearBufferf(bufferIndex, clearValue2); - - // THEN - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - for (const QVector4D c : colors) { - QVERIFY(c == clearValue2); - } - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void createFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // WHEN - const GLuint fboId = m_glHelper.createFrameBufferObject(); - - // THEN - QVERIFY(fboId != 0); - - // Restore - m_func->glDeleteFramebuffers(1, &fboId); - } - - void depthMask() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLboolean depthWritingEnabled = false; - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - - // THEN - QVERIFY(depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_FALSE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(!depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_TRUE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(depthWritingEnabled); - } - - void depthTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_DEPTH_TEST); - m_func->glDepthFunc(GL_LESS); - - // WHEN - m_glHelper.depthTest(GL_LEQUAL); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - GLint depthMode = 0; - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LEQUAL); - - // WHEN - m_glHelper.depthTest(GL_LESS); - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LESS); - } - - void disableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_CLIP_DISTANCE0 + 5); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - - // WHEN - m_glHelper.disableClipPlane(5); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - } - - void disablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glEnablei(GL_BLEND, 2); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); - - // WHEN - m_glHelper.disablei(GL_BLEND, 2); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); - } - - void disablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.disablePrimitiveRestart(); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - } - - void drawBuffers() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - QOpenGLTexture *textures[4]; - - // Create 4 attachments - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // WHEN - GLenum bufferEnum = GL_COLOR_ATTACHMENT4; - m_func->glDrawBuffers(1, &bufferEnum); - - // THEN - GLint enumValue = -1; - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); - - // WHEN - GLint newBufferEnum = 2; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // WHEN - newBufferEnum = 0; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void enableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_CLIP_DISTANCE0 + 4); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - - // WHEN - m_glHelper.enableClipPlane(4); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - } - - void enablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisablei(GL_BLEND, 4); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); - - // WHEN - m_glHelper.enablei(GL_BLEND, 4); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); - } - - void enablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.enablePrimitiveRestart(883); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - GLint restartIndex = 0; - m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); - QCOMPARE(restartIndex, 883); - - // Restore - m_func->glDisable(GL_PRIMITIVE_RESTART); - } - - void enableVertexAttribute() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - shaderProgram.bind(); - - // WHEN - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void frontFace() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glFrontFace(GL_CW); - - // THEN - GLint face = 0; - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CW); - - // WHEN - m_glHelper.frontFace(GL_CCW); - - // THEN - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CCW); - } - - void getRenderBufferDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint renderBufferId = 0; - m_func->glGenRenderbuffers(1, &renderBufferId); - QVERIFY(renderBufferId != 0); - - // WHEN - m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); - m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); - m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); - const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - - // Restore - m_func->glDeleteRenderbuffers(1, &renderBufferId); - } - - void getTextureDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - - // WHEN - const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - } - - void pointSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PROGRAM_POINT_SIZE); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - GLfloat size = 0; - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 1.0f); - - // WHEN - m_glHelper.pointSize(false, 0.5f); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 0.5f); - } - - void maxClipPlaneCount() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLint maxCount = -1; - m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); - - // THEN - QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); - } - - void programUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniformBlocks.size(), 1); - const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); - - QCOMPARE(uniformBlock.m_activeUniformsCount, 1); - QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); - - GLint blockIndex = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); - GLint blockBinding = -1; - m_func->glGetActiveUniformBlockiv(shaderProgram.programId(), blockIndex, GL_UNIFORM_BLOCK_BINDING, &blockBinding); - QCOMPARE(blockIndex, uniformBlock.m_index); - QCOMPARE(blockBinding, uniformBlock.m_binding); - } - - void programAttributesAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeAttributes.size(), 2); - std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); - - const ShaderAttribute attribute1 = activeAttributes.at(0); - QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); - QCOMPARE(attribute1.m_size, 1); - QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); - QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); - - const ShaderAttribute attribute2 = activeAttributes.at(1); - QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); - QCOMPARE(attribute2.m_size, 1); - QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); - QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); - } - - void programUniformsAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniforms.size(), 4); - std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); - - const ShaderUniform uniform1 = activeUniforms.at(0); - QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); - QCOMPARE(uniform1.m_offset, -1); - QCOMPARE(uniform1.m_blockIndex, -1); - QCOMPARE(uniform1.m_arrayStride, -1); - QCOMPARE(uniform1.m_matrixStride, -1); - QCOMPARE(uniform1.m_size, 1); - QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); - QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); - - const ShaderUniform uniform2 = activeUniforms.at(1); - QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); - QCOMPARE(uniform2.m_offset, -1); - QCOMPARE(uniform2.m_blockIndex, -1); - QCOMPARE(uniform2.m_arrayStride, -1); - QCOMPARE(uniform2.m_matrixStride, -1); - QCOMPARE(uniform2.m_size, 1); - QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); - QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); - - const ShaderUniform uniform3 = activeUniforms.at(2); - QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); - QCOMPARE(uniform3.m_offset, -1); - QCOMPARE(uniform3.m_blockIndex, -1); - QCOMPARE(uniform3.m_arrayStride, -1); - QCOMPARE(uniform3.m_matrixStride, -1); - QCOMPARE(uniform3.m_size, 1); - QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); - QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); - - const ShaderUniform uniform4 = activeUniforms.at(3); - QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); - QCOMPARE(uniform4.m_offset, -1); - QCOMPARE(uniform4.m_blockIndex, -1); - QCOMPARE(uniform4.m_arrayStride, -1); - QCOMPARE(uniform4.m_matrixStride, -1); - QCOMPARE(uniform4.m_size, 1); - QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); - QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); - } - - void programShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // Not supported in 3.2 - } - - void releaseFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.releaseFrameBufferObject(fboId); - - // THEN - QVERIFY(!m_func->glIsFramebuffer(fboId)); - } - - void setMSAAEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_MULTISAMPLE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - } - - void setAlphaCoverageEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - } - - void setClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // Deprecated in 3.3 core - } - - void setSeamlessCubemap() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - - void setVerticesPerPatch() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - -#define SUPPORTS_FEATURE(Feature, IsSupported) \ - QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); - - void supportsFeature() - { - SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); - // Tesselation could be true or false depending on extensions so not tested - SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, true); - } - - -#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ - QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; - - void uniformsByteSize_data() - { - QTest::addColumn("fragShader"); - QTest::addColumn("name"); - QTest::addColumn("type"); - QTest::addColumn("componentSize"); - QTest::addColumn("expectedByteSize"); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplier", GL_UNSIGNED_INT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec2", GL_UNSIGNED_INT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec3", GL_UNSIGNED_INT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec4", GL_UNSIGNED_INT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2a", GL_SAMPLER_2D_ARRAY, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "srect", GL_SAMPLER_2D_RECT, 1, 4); - } - - void uniformsByteSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QFETCH(QByteArray, fragShader); - QFETCH(QString, name); - QFETCH(int, type); - QFETCH(int, componentSize); - QFETCH(int, expectedByteSize); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); - QVERIFY(shaderProgram.link()); - - GLint location = shaderProgram.uniformLocation(name); - // WHEN - const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - ShaderUniform matchingUniform; - for (const ShaderUniform &u : activeUniforms) { - if (u.m_location == location) { - matchingUniform = u; - break; - } - } - - - // THEN - QCOMPARE(matchingUniform.m_location, location); - QCOMPARE(matchingUniform.m_type, GLuint(type)); - QCOMPARE(matchingUniform.m_size, componentSize); - - // WHEN - const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); - - // THEN - QCOMPARE(expectedByteSize, computedRawByteSize); - - // Restore - m_func->glUseProgram(0); - } - - void useProgram() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // THEN - QVERIFY(shaderProgram.link()); - - GLint currentProg = 0; - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - - // WHEN - m_glHelper.useProgram(shaderProgram.programId()); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QCOMPARE(GLuint(currentProg), shaderProgram.programId()); - - // WHEN - m_glHelper.useProgram(0); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - } - - void vertexAttribDivisor() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - // Not available in 3.2 - } - - void vertexAttributePointer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - - const int vertexCount = 99; - QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); - positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - positionBuffer.create(); - positionBuffer.bind(); - positionBuffer.allocate(vertexCount * sizeof(QVector3D)); - - QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); - texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - texCoordBuffer.create(); - texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); - - QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); - colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - colorIndexBuffer.create(); - colorIndexBuffer.allocate(vertexCount * sizeof(int)); - - // WHEN - shaderProgram.bind(); - positionBuffer.bind(); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); - - texCoordBuffer.bind(); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); - - colorIndexBuffer.bind(); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void glUniform1fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat value = 883.0f; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1fv(location, 1, &value); - - // THEN - GLfloat setValue = 0.0f; - m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[2] = { 383.0f, 427.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2fv(location, 1, values); - - // THEN - GLfloat setValues[2] = { 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3fv(location, 1, values); - - // THEN - GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint value = 883; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1iv(location, 1, &value); - - // THEN - GLint setValue = 0; - m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[2] = { 383, 427 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2iv(location, 1, values); - - // THEN - GLint setValues[2] = { 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[3] = { 572, 1340, 1584 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3iv(location, 1, values); - - // THEN - GLint setValues[3] = { 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[4] = { 454, 350, 883, 355 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4iv(location, 1, values); - - // THEN - GLint setValues[4] = { 0, 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint value = 883U; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1uiv(location, 1, &value); - - // THEN - GLuint setValue = 0U; - m_func->glGetUniformuiv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[2] = { 383U, 427U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2uiv(location, 1, values); - - // THEN - GLuint setValues[2] = { 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[3] = { 572U, 1340U, 1584U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3uiv(location, 1, values); - - // THEN - GLuint setValues[3] = { 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[4] = { 454U, 350U, 883U, 355U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4uiv(location, 1, values); - - // THEN - GLuint setValues[4] = { 0U, 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("m2"); - m_glHelper.glUniformMatrix2fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; - const GLint location = shaderProgram.uniformLocation("m3"); - m_glHelper.glUniformMatrix3fv(location, 1, values); - - // THEN - GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 9; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; - const GLint location = shaderProgram.uniformLocation("m4"); - m_glHelper.glUniformMatrix4fv(location, 1, values); - - // THEN - GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 16; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m23"); - m_glHelper.glUniformMatrix2x3fv(location, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m32"); - m_glHelper.glUniformMatrix3x2fv(location, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m24"); - m_glHelper.glUniformMatrix2x4fv(location, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m42"); - m_glHelper.glUniformMatrix4x2fv(location, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f}; - const GLint location = shaderProgram.uniformLocation("m34"); - m_glHelper.glUniformMatrix3x4fv(location, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m43"); - m_glHelper.glUniformMatrix4x3fv(location, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void blitFramebuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - GLint maxSamples; - m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); - if (maxSamples < 1) - QSKIP("This test requires an implementation that supports multisampled textures"); - - // GIVEN - GLuint fbos[2]; - GLuint fboTextures[2]; - - m_func->glGenFramebuffers(2, fbos); - m_func->glGenTextures(2, fboTextures); - - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); - m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - - m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); - m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - m_func->glBindTexture(GL_TEXTURE_2D, 0); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); - - GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); - - status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - m_func->glEnable(GL_MULTISAMPLE); - m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); - m_func->glClear(GL_COLOR_BUFFER_BIT); - m_func->glDisable(GL_MULTISAMPLE); - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); - - // WHEN - m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); - - GLuint result[10*10]; - m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); - - // THEN - GLuint v = (0.2f) * 255; - v = v | (v<<8) | (v<<16) | (v<<24); - for (GLuint value : result) { - QCOMPARE(value, v); - } - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - m_func->glDeleteFramebuffers(2, fbos); - m_func->glDeleteTextures(2, fboTextures); - } - -#define ADD_GL_TYPE_ENTRY(Type, Expected) \ - QTest::newRow(#Type) << Type << Expected; - - void uniformTypeFromGLType_data() - { - QTest::addColumn("glType"); - QTest::addColumn("expected"); - - ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); - ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); - ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); - ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); - ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); - } - - void uniformTypeFromGLType() - { - // GIVEN - QFETCH(int, glType); - QFETCH(UniformType, expected); - - // WHEN - UniformType computed = m_glHelper.uniformTypeFromGLType(glType); - - // THEN - QCOMPARE(computed, expected); - } - - void drawBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.drawBuffer(GL_FRONT); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - GLint p; - m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void readBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.readBuffer(GL_FRONT); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_READ_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void fenceSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - // THEN - QVERIFY(sync != nullptr); - QCOMPARE(m_func->glIsSync(sync), GL_TRUE); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void clientWaitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - QElapsedTimer t; - t.start(); - - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - m_glHelper.clientWaitSync(sync, 1000000); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - qDebug() << t.nsecsElapsed(); - } - - void waitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void wasSyncSignaled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // Shouldn't loop forever - while (!m_glHelper.wasSyncSignaled(sync)) - ; - } - - void deleteSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_glHelper.clientWaitSync(sync, GLuint64(-1)); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); - - // WHEN - m_glHelper.deleteSync(sync); - - // THEN - QCOMPARE(m_func->glIsSync(sync), GL_FALSE); - } - - void rasterMode() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.2 functions not supported"); - - m_func->glGetError(); - - m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_POLYGON_MODE, &p); - QCOMPARE(p, GL_LINE); - } - -private: - QScopedPointer m_window; - QOpenGLContext m_glContext; - GraphicsHelperGL3_2 m_glHelper; - QOpenGLFunctions_3_2_Core *m_func = nullptr; - bool m_initializationSuccessful = false; -}; - -#endif - -int main(int argc, char *argv[]) -{ -#ifdef TEST_SHOULD_BE_PERFORMED - QGuiApplication app(argc, argv); - app.setAttribute(Qt::AA_Use96Dpi, true); - tst_GraphicsHelperGL3_2 tc; - QTEST_SET_MAIN_SOURCE_PATH - return QTest::qExec(&tc, argc, argv); -#endif - return 0; -} - -#ifdef TEST_SHOULD_BE_PERFORMED -#include "tst_graphicshelpergl3_2.moc" -#endif diff --git a/tests/auto/render/graphicshelpergl3_3/graphicshelpergl3_3.pro b/tests/auto/render/graphicshelpergl3_3/graphicshelpergl3_3.pro deleted file mode 100644 index 36bda15b2..000000000 --- a/tests/auto/render/graphicshelpergl3_3/graphicshelpergl3_3.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE = app - -TARGET = tst_graphicshelpergl3_3 - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += \ - tst_graphicshelpergl3_3.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp deleted file mode 100644 index 874c83f0b..000000000 --- a/tests/auto/render/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp +++ /dev/null @@ -1,2393 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) - -#define TEST_SHOULD_BE_PERFORMED 1 - -using namespace Qt3DRender; -using namespace Qt3DRender::Render; - -namespace { - -const QByteArray vertCode = QByteArrayLiteral( - "#version 330 core\n" \ - "in vec3 vertexPosition;\n" \ - "in vec2 vertexTexCoord;\n" \ - "out vec2 texCoord;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( - "#version 330 core\n" \ - "in vec3 vertexPosition;\n" \ - "in vec2 vertexTexCoord;\n" \ - "in int vertexColorIndex;\n" \ - "out vec2 texCoord;\n" \ - "flat out int colorIndex;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " colorIndex = vertexColorIndex;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeFragOutputs = QByteArrayLiteral( - "#version 330 core\n" \ - "out vec4 color;\n" \ - "out vec2 temp;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ - " temp = vec2(1.0, 0.3);\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( - "#version 330 core\n" \ - "out vec4 color;\n" \ - "uniform float multiplier;\n" \ - "uniform vec2 multiplierVec2;\n" \ - "uniform vec3 multiplierVec3;\n" \ - "uniform vec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsInt = QByteArrayLiteral( - "#version 330 core\n" \ - "out ivec4 color;\n" \ - "uniform int multiplier;\n" \ - "uniform ivec2 multiplierVec2;\n" \ - "uniform ivec3 multiplierVec3;\n" \ - "uniform ivec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ - " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( - "#version 330 core\n" \ - "out uvec4 color;\n" \ - "uniform uint multiplier;\n" \ - "uniform uvec2 multiplierVec2;\n" \ - "uniform uvec3 multiplierVec3;\n" \ - "uniform uvec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ - " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( - "#version 330 core\n" \ - "out vec4 color;\n" \ - "uniform mat2 m2;\n" \ - "uniform mat2x3 m23;\n" \ - "uniform mat3x2 m32;\n" \ - "uniform mat2x4 m24;\n" \ - "uniform mat4x2 m42;\n" \ - "uniform mat3 m3;\n" \ - "uniform mat3x4 m34;\n" \ - "uniform mat4x3 m43;\n" \ - "uniform mat4 m4;\n" \ - "void main()\n" \ - "{\n" \ - " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ - " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ - "}\n"); - -const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( - "#version 330 core\n" \ - "out vec4 color;\n" \ - "in vec2 texCoord;\n" \ - "flat in int colorIndex;\n" \ - "uniform ColorArray\n" \ - "{\n" \ - " vec4 colors[256];\n" \ - "};\n" \ - "void main()\n" \ - "{\n" \ - " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeSamplers = QByteArrayLiteral( - "#version 330 core\n" \ - "in vec2 texCoord;\n" \ - "out vec4 color;\n" \ - "uniform sampler1D s1;\n" \ - "uniform sampler2D s2;\n" \ - "uniform sampler2DArray s2a;\n" \ - "uniform sampler3D s3;\n" \ - "uniform samplerCube scube;\n" \ - "uniform sampler2DRect srect;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1, 0, 0, 1) *" \ - " texture(s1, texCoord.x) *" \ - " texture(s2, texCoord) *" \ - " texture(s2a, vec3(texCoord, 0.0)) *" \ - " texture(s3, vec3(texCoord, 0.0)) *" \ - " texture(scube, vec3(texCoord, 0)) *" \ - " texture(srect, texCoord);\n" \ - "}\n"); - -} // anonymous - -class tst_GraphicsHelperGL3_3 : public QObject -{ - Q_OBJECT -private Q_SLOTS: - - void init() - { - m_window.reset(new QWindow); - m_window->setSurfaceType(QWindow::OpenGLSurface); - m_window->setGeometry(0, 0, 10, 10); - - QSurfaceFormat format; - format.setVersion(3, 3); - format.setProfile(QSurfaceFormat::CoreProfile); - format.setDepthBufferSize(24); - format.setSamples(4); - format.setStencilBufferSize(8); - m_window->setFormat(format); - m_glContext.setFormat(format); - - m_window->create(); - - if (!m_glContext.create()) { - qWarning() << "Failed to create OpenGL context"; - return; - } - - if (!m_glContext.makeCurrent(m_window.data())) { - qWarning() << "Failed to maed OpenGL context current"; - return; - } - - if ((m_func = m_glContext.versionFunctions()) != nullptr) { - m_glHelper.initializeHelper(&m_glContext, m_func); - m_initializationSuccessful = true; - } - } - - void cleanup() - { - m_glContext.doneCurrent(); - } - - void alphaTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - // Deprecated - } - - void bindBufferBase() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint bufferId = 0; - // WHEN - m_func->glGenBuffers(1, &bufferId); - // THEN - QVERIFY(bufferId != 0); - - - // WHEN - m_func->glBindBuffer(GL_UNIFORM_BUFFER, bufferId); - m_glHelper.bindBufferBase(GL_UNIFORM_BUFFER, 2, bufferId); - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundToPointBufferId = 0; - m_func->glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, 2, &boundToPointBufferId); - QVERIFY(boundToPointBufferId == GLint(bufferId)); - - // Restore to sane state - m_func->glBindBuffer(GL_UNIFORM_BUFFER, 0); - m_func->glDeleteBuffers(1, &bufferId); - } - - void bindFragDataLocation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // WHEN - QHash fragLocations; - fragLocations.insert(QStringLiteral("temp"), 2); - fragLocations.insert(QStringLiteral("color"), 1); - m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); - - // THEN - QVERIFY(shaderProgram.link()); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); - const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); - QCOMPARE(tempLocation, 2); - QCOMPARE(colorLocation, 1); - } - - void bindFrameBufferAttachment() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - { - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - GLint maxAttachmentsCount = 0; - m_func->glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachmentsCount); - - // THEN - QVERIFY(fboId != 0); - QVERIFY(maxAttachmentsCount >= 3); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QCOMPARE(int(status), GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureAttachmentId = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &textureAttachmentId); - QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - { - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA32F); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - { // Check All Faces - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; - - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureIsLayered = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_LAYERED, - &textureIsLayered); - QCOMPARE(textureIsLayered, GL_TRUE); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - { // Check Specific Faces - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; - - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureFace = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, - &textureFace); - QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); - GLint textureIsLayered = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_LAYERED, - &textureIsLayered); - QCOMPARE(textureIsLayered, GL_FALSE); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - } - } - - void bindFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - - // THEN - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundindFBOId = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // Cleanup - m_func->glDeleteFramebuffers(1, &fboId); - } - - void bindShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - // Not supported in OpenGL 3.3 - } - - void bindUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); - m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void blendEquation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLint equation = 0; - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_ADD); - - // WHEN - m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); - - // THEN - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); - } - - void blendFunci() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - // Not supported by OpenGL 3.3 - } - - void blendFuncSeparatei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // Not supported by OpenGL 3.3 - } - - void boundFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - // THEN - GLint boundBuffer = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); - QCOMPARE(GLuint(boundBuffer), fboId); - - // THEN - QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); - - // Reset state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void checkFrameBufferComplete() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - QVERIFY(m_glHelper.checkFrameBufferComplete()); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void clearBufferf() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - // Create 4 attachments - QOpenGLTexture *textures[4]; - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // Set Draw buffers - GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; - m_func->glDrawBuffers(1, &clearBufferEnum); - - const GLint bufferIndex = 0; // index of the element in the draw buffers - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // WHEN - const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); - m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); - error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - QVector colors(512 * 512); - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - - for (const QVector4D c : colors) { - QVERIFY(c == clearValue1); - } - - // WHEN - const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); - m_glHelper.clearBufferf(bufferIndex, clearValue2); - - // THEN - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - for (const QVector4D c : colors) { - QVERIFY(c == clearValue2); - } - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void createFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // WHEN - const GLuint fboId = m_glHelper.createFrameBufferObject(); - - // THEN - QVERIFY(fboId != 0); - - // Restore - m_func->glDeleteFramebuffers(1, &fboId); - } - - void depthMask() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLboolean depthWritingEnabled = false; - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - - // THEN - QVERIFY(depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_FALSE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(!depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_TRUE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(depthWritingEnabled); - } - - void depthTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_DEPTH_TEST); - m_func->glDepthFunc(GL_LESS); - - // WHEN - m_glHelper.depthTest(GL_LEQUAL); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - GLint depthMode = 0; - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LEQUAL); - - // WHEN - m_glHelper.depthTest(GL_LESS); - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LESS); - } - - void disableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_CLIP_DISTANCE0 + 5); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - - // WHEN - m_glHelper.disableClipPlane(5); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - } - - void disablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glEnablei(GL_BLEND, 2); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); - - // WHEN - m_glHelper.disablei(GL_BLEND, 2); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); - } - - void disablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.disablePrimitiveRestart(); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - } - - void drawBuffers() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - QOpenGLTexture *textures[4]; - - // Create 4 attachments - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // WHEN - GLenum bufferEnum = GL_COLOR_ATTACHMENT4; - m_func->glDrawBuffers(1, &bufferEnum); - - // THEN - GLint enumValue = -1; - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); - - // WHEN - GLint newBufferEnum = 2; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // WHEN - newBufferEnum = 0; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void enableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_CLIP_DISTANCE0 + 4); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - - // WHEN - m_glHelper.enableClipPlane(4); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - } - - void enablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisablei(GL_BLEND, 4); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); - - // WHEN - m_glHelper.enablei(GL_BLEND, 4); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); - } - - void enablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.enablePrimitiveRestart(883); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - GLint restartIndex = 0; - m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); - QCOMPARE(restartIndex, 883); - - // Restore - m_func->glDisable(GL_PRIMITIVE_RESTART); - } - - void enableVertexAttribute() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - shaderProgram.bind(); - - // WHEN - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void frontFace() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glFrontFace(GL_CW); - - // THEN - GLint face = 0; - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CW); - - // WHEN - m_glHelper.frontFace(GL_CCW); - - // THEN - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CCW); - } - - void getRenderBufferDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint renderBufferId = 0; - m_func->glGenRenderbuffers(1, &renderBufferId); - QVERIFY(renderBufferId != 0); - - // WHEN - m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); - m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); - m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); - const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - - // Restore - m_func->glDeleteRenderbuffers(1, &renderBufferId); - } - - void getTextureDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - - // WHEN - const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - } - - void pointSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PROGRAM_POINT_SIZE); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - GLfloat size = 0; - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 1.0f); - - // WHEN - m_glHelper.pointSize(false, 0.5f); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 0.5f); - } - - void maxClipPlaneCount() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLint maxCount = -1; - m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); - - // THEN - QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); - } - - void programUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniformBlocks.size(), 1); - const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); - - QCOMPARE(uniformBlock.m_activeUniformsCount, 1); - QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); - - GLint blockIndex = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); - GLint blockBinding = -1; - m_func->glGetActiveUniformBlockiv(shaderProgram.programId(), blockIndex, GL_UNIFORM_BLOCK_BINDING, &blockBinding); - QCOMPARE(blockIndex, uniformBlock.m_index); - QCOMPARE(blockBinding, uniformBlock.m_binding); - } - - void programAttributesAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeAttributes.size(), 2); - std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); - - const ShaderAttribute attribute1 = activeAttributes.at(0); - QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); - QCOMPARE(attribute1.m_size, 1); - QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); - QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); - - const ShaderAttribute attribute2 = activeAttributes.at(1); - QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); - QCOMPARE(attribute2.m_size, 1); - QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); - QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); - } - - void programUniformsAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniforms.size(), 4); - std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); - - const ShaderUniform uniform1 = activeUniforms.at(0); - QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); - QCOMPARE(uniform1.m_offset, -1); - QCOMPARE(uniform1.m_blockIndex, -1); - QCOMPARE(uniform1.m_arrayStride, -1); - QCOMPARE(uniform1.m_matrixStride, -1); - QCOMPARE(uniform1.m_size, 1); - QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); - QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); - - const ShaderUniform uniform2 = activeUniforms.at(1); - QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); - QCOMPARE(uniform2.m_offset, -1); - QCOMPARE(uniform2.m_blockIndex, -1); - QCOMPARE(uniform2.m_arrayStride, -1); - QCOMPARE(uniform2.m_matrixStride, -1); - QCOMPARE(uniform2.m_size, 1); - QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); - QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); - - const ShaderUniform uniform3 = activeUniforms.at(2); - QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); - QCOMPARE(uniform3.m_offset, -1); - QCOMPARE(uniform3.m_blockIndex, -1); - QCOMPARE(uniform3.m_arrayStride, -1); - QCOMPARE(uniform3.m_matrixStride, -1); - QCOMPARE(uniform3.m_size, 1); - QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); - QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); - - const ShaderUniform uniform4 = activeUniforms.at(3); - QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); - QCOMPARE(uniform4.m_offset, -1); - QCOMPARE(uniform4.m_blockIndex, -1); - QCOMPARE(uniform4.m_arrayStride, -1); - QCOMPARE(uniform4.m_matrixStride, -1); - QCOMPARE(uniform4.m_size, 1); - QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); - QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); - } - - void programShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // Not supported in 3.3 - } - - void releaseFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.releaseFrameBufferObject(fboId); - - // THEN - QVERIFY(!m_func->glIsFramebuffer(fboId)); - } - - void setMSAAEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_MULTISAMPLE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - } - - void setAlphaCoverageEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - } - - void setClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // Deprecated in 3.3 core - } - - void setSeamlessCubemap() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - - void setVerticesPerPatch() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - -#define SUPPORTS_FEATURE(Feature, IsSupported) \ - QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); - - void supportsFeature() - { - SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); - SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); - SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); - // Tesselation could be true or false depending on extensions so not tested - SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, true); - } - - -#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ - QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; - - void uniformsByteSize_data() - { - QTest::addColumn("fragShader"); - QTest::addColumn("name"); - QTest::addColumn("type"); - QTest::addColumn("componentSize"); - QTest::addColumn("expectedByteSize"); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplier", GL_UNSIGNED_INT, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec2", GL_UNSIGNED_INT_VEC2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec3", GL_UNSIGNED_INT_VEC3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec4", GL_UNSIGNED_INT_VEC4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2a", GL_SAMPLER_2D_ARRAY, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, "srect", GL_SAMPLER_2D_RECT, 1, 4); - } - - void uniformsByteSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QFETCH(QByteArray, fragShader); - QFETCH(QString, name); - QFETCH(int, type); - QFETCH(int, componentSize); - QFETCH(int, expectedByteSize); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); - QVERIFY(shaderProgram.link()); - - GLint location = shaderProgram.uniformLocation(name); - // WHEN - const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - ShaderUniform matchingUniform; - for (const ShaderUniform &u : activeUniforms) { - if (u.m_location == location) { - matchingUniform = u; - break; - } - } - - - // THEN - QCOMPARE(matchingUniform.m_location, location); - QCOMPARE(matchingUniform.m_type, GLuint(type)); - QCOMPARE(matchingUniform.m_size, componentSize); - - // WHEN - const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); - - // THEN - QCOMPARE(expectedByteSize, computedRawByteSize); - - // Restore - m_func->glUseProgram(0); - } - - - void useProgram() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // THEN - QVERIFY(shaderProgram.link()); - - GLint currentProg = 0; - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - - // WHEN - m_glHelper.useProgram(shaderProgram.programId()); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QCOMPARE(GLuint(currentProg), shaderProgram.programId()); - - // WHEN - m_glHelper.useProgram(0); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - } - - void vertexAttribDivisor() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - } - - void vertexAttributePointer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - - const int vertexCount = 99; - QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); - positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - positionBuffer.create(); - positionBuffer.bind(); - positionBuffer.allocate(vertexCount * sizeof(QVector3D)); - - QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); - texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - texCoordBuffer.create(); - texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); - - QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); - colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - colorIndexBuffer.create(); - colorIndexBuffer.allocate(vertexCount * sizeof(int)); - - // WHEN - shaderProgram.bind(); - positionBuffer.bind(); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); - - texCoordBuffer.bind(); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); - - colorIndexBuffer.bind(); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void glUniform1fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat value = 883.0f; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1fv(location, 1, &value); - - // THEN - GLfloat setValue = 0.0f; - m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[2] = { 383.0f, 427.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2fv(location, 1, values); - - // THEN - GLfloat setValues[2] = { 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3fv(location, 1, values); - - // THEN - GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint value = 883; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1iv(location, 1, &value); - - // THEN - GLint setValue = 0; - m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[2] = { 383, 427 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2iv(location, 1, values); - - // THEN - GLint setValues[2] = { 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[3] = { 572, 1340, 1584 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3iv(location, 1, values); - - // THEN - GLint setValues[3] = { 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[4] = { 454, 350, 883, 355 }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4iv(location, 1, values); - - // THEN - GLint setValues[4] = { 0, 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint value = 883U; - const GLint location = shaderProgram.uniformLocation("multiplier"); - m_glHelper.glUniform1uiv(location, 1, &value); - - // THEN - GLuint setValue = 0U; - m_func->glGetUniformuiv(shaderProgram.programId(), location, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[2] = { 383U, 427U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec2"); - m_glHelper.glUniform2uiv(location, 1, values); - - // THEN - GLuint setValues[2] = { 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[3] = { 572U, 1340U, 1584U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec3"); - m_glHelper.glUniform3uiv(location, 1, values); - - // THEN - GLuint setValues[3] = { 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[4] = { 454U, 350U, 883U, 355U }; - const GLint location = shaderProgram.uniformLocation("multiplierVec4"); - m_glHelper.glUniform4uiv(location, 1, values); - - // THEN - GLuint setValues[4] = { 0U, 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - const GLint location = shaderProgram.uniformLocation("m2"); - m_glHelper.glUniformMatrix2fv(location, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; - const GLint location = shaderProgram.uniformLocation("m3"); - m_glHelper.glUniformMatrix3fv(location, 1, values); - - // THEN - GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 9; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; - const GLint location = shaderProgram.uniformLocation("m4"); - m_glHelper.glUniformMatrix4fv(location, 1, values); - - // THEN - GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 16; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m23"); - m_glHelper.glUniformMatrix2x3fv(location, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m32"); - m_glHelper.glUniformMatrix3x2fv(location, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m24"); - m_glHelper.glUniformMatrix2x4fv(location, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m42"); - m_glHelper.glUniformMatrix4x2fv(location, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f}; - const GLint location = shaderProgram.uniformLocation("m34"); - m_glHelper.glUniformMatrix3x4fv(location, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - const GLint location = shaderProgram.uniformLocation("m43"); - m_glHelper.glUniformMatrix4x3fv(location, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - - void blitFramebuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - GLint maxSamples; - m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); - if (maxSamples < 1) - QSKIP("This test requires an implementation that supports multisampled textures"); - - // GIVEN - GLuint fbos[2]; - GLuint fboTextures[2]; - - m_func->glGenFramebuffers(2, fbos); - m_func->glGenTextures(2, fboTextures); - - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); - m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - - m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); - m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - m_func->glBindTexture(GL_TEXTURE_2D, 0); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); - - GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); - - status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); - - m_func->glEnable(GL_MULTISAMPLE); - m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); - m_func->glClear(GL_COLOR_BUFFER_BIT); - m_func->glDisable(GL_MULTISAMPLE); - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); - - // WHEN - m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); - - GLuint result[10*10]; - m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); - - // THEN - GLuint v = (0.2f) * 255; - v = v | (v<<8) | (v<<16) | (v<<24); - for (GLuint value : result) { - QCOMPARE(value, v); - } - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - m_func->glDeleteFramebuffers(2, fbos); - m_func->glDeleteTextures(2, fboTextures); - } - -#define ADD_GL_TYPE_ENTRY(Type, Expected) \ - QTest::newRow(#Type) << Type << Expected; - - void uniformTypeFromGLType_data() - { - QTest::addColumn("glType"); - QTest::addColumn("expected"); - - ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); - ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); - ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); - ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); - ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); - } - - void uniformTypeFromGLType() - { - // GIVEN - QFETCH(int, glType); - QFETCH(UniformType, expected); - - // WHEN - UniformType computed = m_glHelper.uniformTypeFromGLType(glType); - - // THEN - QCOMPARE(computed, expected); - } - - void drawBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.drawBuffer(GL_FRONT); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - GLint p; - m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void readBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.readBuffer(GL_FRONT); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_READ_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void fenceSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - // THEN - QVERIFY(sync != nullptr); - QCOMPARE(m_func->glIsSync(sync), GL_TRUE); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void clientWaitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - QElapsedTimer t; - t.start(); - - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - m_glHelper.clientWaitSync(sync, 1000000); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - qDebug() << t.nsecsElapsed(); - } - - void waitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void wasSyncSignaled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // Shouldn't loop forever - while (!m_glHelper.wasSyncSignaled(sync)) - ; - } - - void deleteSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_glHelper.clientWaitSync(sync, GLuint64(-1)); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); - - // WHEN - m_glHelper.deleteSync(sync); - - // THEN - QCOMPARE(m_func->glIsSync(sync), GL_FALSE); - } - - void rasterMode() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 3.3 functions not supported"); - - m_func->glGetError(); - m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_POLYGON_MODE, &p); - QCOMPARE(p, GL_LINE); - } - -private: - QScopedPointer m_window; - QOpenGLContext m_glContext; - GraphicsHelperGL3_3 m_glHelper; - QOpenGLFunctions_3_3_Core *m_func = nullptr; - bool m_initializationSuccessful = false; -}; - -#endif - -int main(int argc, char *argv[]) -{ -#ifdef TEST_SHOULD_BE_PERFORMED - QGuiApplication app(argc, argv); - app.setAttribute(Qt::AA_Use96Dpi, true); - tst_GraphicsHelperGL3_3 tc; - QTEST_SET_MAIN_SOURCE_PATH - return QTest::qExec(&tc, argc, argv); -#endif - return 0; -} - -#ifdef TEST_SHOULD_BE_PERFORMED -#include "tst_graphicshelpergl3_3.moc" -#endif diff --git a/tests/auto/render/graphicshelpergl4/graphicshelpergl4.pro b/tests/auto/render/graphicshelpergl4/graphicshelpergl4.pro deleted file mode 100644 index b20d1afec..000000000 --- a/tests/auto/render/graphicshelpergl4/graphicshelpergl4.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE = app - -TARGET = tst_graphicshelpergl4 - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += \ - tst_graphicshelpergl4.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp deleted file mode 100644 index 6e5c54303..000000000 --- a/tests/auto/render/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ /dev/null @@ -1,2583 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_4_3) - -#define TEST_SHOULD_BE_PERFORMED 1 - -using namespace Qt3DRender; -using namespace Qt3DRender::Render; - -namespace { - -const QByteArray vertCode = QByteArrayLiteral( - "#version 430 core\n" \ - "layout(location = 1) in vec3 vertexPosition;\n" \ - "layout(location = 2) in vec2 vertexTexCoord;\n" \ - "out vec2 texCoord;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vertexTexCoord;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( - "#version 430 core\n" \ - "layout(location = 1) in vec3 vertexPosition;\n" \ - "layout(location = 2) in vec2 vertexTexCoord;\n" \ - "layout(location = 3) in int vertexColorIndex;\n" \ - "layout(location = 4) in double vertexTexCoordScale;\n" \ - "out vec2 texCoord;\n" \ - "flat out int colorIndex;\n" \ - "void main()\n" \ - "{\n" \ - " texCoord = vec2(vertexTexCoordScale * vertexTexCoord);\n" \ - " colorIndex = vertexColorIndex;\n" \ - " gl_Position = vec4(vertexPosition, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeFragOutputs = QByteArrayLiteral( - "#version 430 core\n" \ - "out vec4 color;\n" \ - "out vec2 temp;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ - " temp = vec2(1.0, 0.3);\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( - "#version 430 core\n" \ - "out vec4 color;\n" \ - "layout(location = 1) uniform float multiplier;\n" \ - "layout(location = 2) uniform vec2 multiplierVec2;\n" \ - "layout(location = 3) uniform vec3 multiplierVec3;\n" \ - "layout(location = 4) uniform vec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ - " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsInt = QByteArrayLiteral( - "#version 430 core\n" \ - "out ivec4 color;\n" \ - "layout(location = 1) uniform int multiplier;\n" \ - "layout(location = 2) uniform ivec2 multiplierVec2;\n" \ - "layout(location = 3) uniform ivec3 multiplierVec3;\n" \ - "layout(location = 4) uniform ivec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ - " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( - "#version 430 core\n" \ - "out uvec4 color;\n" \ - "layout(location = 1) uniform uint multiplier;\n" \ - "layout(location = 2) uniform uvec2 multiplierVec2;\n" \ - "layout(location = 3) uniform uvec3 multiplierVec3;\n" \ - "layout(location = 4) uniform uvec4 multiplierVec4;\n" \ - "void main()\n" \ - "{\n" \ - " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ - " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ - "}\n"); - -const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( - "#version 430 core\n" \ - "out vec4 color;\n" \ - "layout(location = 1) uniform mat2 m2;\n" \ - "layout(location = 2) uniform mat2x3 m23;\n" \ - "layout(location = 3) uniform mat3x2 m32;\n" \ - "layout(location = 4) uniform mat2x4 m24;\n" \ - "layout(location = 5) uniform mat4x2 m42;\n" \ - "layout(location = 6) uniform mat3 m3;\n" \ - "layout(location = 7) uniform mat3x4 m34;\n" \ - "layout(location = 8) uniform mat4x3 m43;\n" \ - "layout(location = 9) uniform mat4 m4;\n" \ - "void main()\n" \ - "{\n" \ - " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ - " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ - "}\n"); - -const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( - "#version 430 core\n" \ - "out vec4 color;\n" \ - "in vec2 texCoord;\n" \ - "flat in int colorIndex;\n" \ - "layout(binding = 2, std140) uniform ColorArray\n" \ - "{\n" \ - " vec4 colors[256];\n" \ - "};\n" \ - "void main()\n" \ - "{\n" \ - " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ - "}\n"); - -const QByteArray fragCodeSamplers = QByteArrayLiteral( - "#version 430 core\n" \ - "in vec2 texCoord;\n" \ - "out vec4 color;\n" \ - "layout(location = 1) uniform sampler1D s1;\n" \ - "layout(location = 2) uniform sampler2D s2;\n" \ - "layout(location = 3) uniform sampler2DArray s2a;\n" \ - "layout(location = 4) uniform sampler3D s3;\n" \ - "layout(location = 5) uniform samplerCube scube;\n" \ - "layout(location = 6) uniform sampler2DRect srect;\n" \ - "void main()\n" \ - "{\n" \ - " color = vec4(1, 0, 0, 1) *" \ - " texture(s1, texCoord.x) *" \ - " texture(s2, texCoord) *" \ - " texture(s2a, vec3(texCoord, 0.0)) *" \ - " texture(s3, vec3(texCoord, 0.0)) *" \ - " texture(scube, vec3(texCoord, 0)) *" \ - " texture(srect, texCoord);\n" \ - "}\n"); - -const QByteArray fragCodeImages = QByteArrayLiteral( - "#version 430 core\n" \ - "in vec2 texCoord;\n" \ - "out vec4 color;\n" \ - "layout(location = 1, rgba32f) readonly uniform image1D s1;\n" \ - "layout(location = 2, rg16f) readonly uniform image2D s2;\n" \ - "layout(location = 3, r16f) readonly uniform image2DArray s2a;\n" \ - "layout(location = 4, rg8) readonly uniform image3D s3;\n" \ - "layout(location = 5, rgba16_snorm) readonly uniform imageCube scube;\n" \ - "layout(location = 6, rg16) readonly uniform image2DRect srect;\n" \ - "void main()\n" \ - "{\n" \ - " ivec2 coords = ivec2(texCoord);\n"\ - " color = vec4(1, 0, 0, 1) *" \ - " imageLoad(s1, coords.x) *" \ - " imageLoad(s2, coords) *" \ - " imageLoad(s2a, ivec3(coords, 0)) *" \ - " imageLoad(s3, ivec3(coords, 0)) *" \ - " imageLoad(scube, ivec3(coords, 0)) *" \ - " imageLoad(srect, coords);\n" \ - "}\n"); - -const QByteArray computeShader = QByteArrayLiteral( - "#version 430 core\n" \ - "uniform float particleStep;\n" \ - "uniform float finalCollisionFactor;\n" \ - "layout (local_size_x = 1024) in;\n" \ - "struct ParticleData\n" \ - "{\n" \ - " vec4 position;\n" \ - " vec4 direction;\n" \ - " vec4 color;\n" \ - "};\n" \ - "layout (std140, binding = 6) coherent buffer Particles\n" \ - "{\n" \ - " ParticleData particles[];\n" \ - "} data;\n" \ - "void main(void)\n" \ - "{\n" \ - " uint globalId = gl_GlobalInvocationID.x;\n" \ - " ParticleData currentParticle = data.particles[globalId];\n" \ - " currentParticle.position = currentParticle.position + currentParticle.direction * particleStep;\n" \ - " vec4 acceleration = normalize(vec4(0.0) - currentParticle.position) * finalCollisionFactor;\n" \ - " currentParticle.direction = currentParticle.direction + acceleration * particleStep;\n" \ - " data.particles[globalId] = currentParticle;\n" \ - "}"); - -} // anonymous - -class tst_GraphicsHelperGL4 : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void init() - { - m_window.reset(new QWindow); - m_window->setSurfaceType(QWindow::OpenGLSurface); - m_window->setGeometry(0, 0, 10, 10); - - QSurfaceFormat format; - format.setVersion(4, 3); - format.setProfile(QSurfaceFormat::CoreProfile); - format.setDepthBufferSize(24); - format.setSamples(4); - format.setStencilBufferSize(8); - m_window->setFormat(format); - m_glContext.setFormat(format); - - m_window->create(); - - if (!m_glContext.create()) { - qWarning() << "Failed to create OpenGL context"; - return; - } - - if (!m_glContext.makeCurrent(m_window.data())) { - qWarning() << "Failed to make OpenGL context current"; - return; - } - - if ((m_func = m_glContext.versionFunctions()) != nullptr) { - m_glHelper.initializeHelper(&m_glContext, m_func); - m_initializationSuccessful = true; - } - } - - void cleanup() - { - m_glContext.doneCurrent(); - } - - void alphaTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - // Deprecated - } - - void bindBufferBase() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint bufferId = 0; - // WHEN - m_func->glGenBuffers(1, &bufferId); - // THEN - QVERIFY(bufferId != 0); - - - // WHEN - m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferId); - m_glHelper.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bufferId); - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundToPointBufferId = 0; - m_func->glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, 2, &boundToPointBufferId); - QVERIFY(boundToPointBufferId == GLint(bufferId)); - - // Restore to sane state - m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); - m_func->glDeleteBuffers(1, &bufferId); - } - - void bindFragDataLocation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // WHEN - QHash fragLocations; - fragLocations.insert(QStringLiteral("temp"), 2); - fragLocations.insert(QStringLiteral("color"), 1); - m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); - - // THEN - QVERIFY(shaderProgram.link()); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); - const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); - QCOMPARE(tempLocation, 2); - QCOMPARE(colorLocation, 1); - } - - void bindFrameBufferAttachment() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - { - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color2; - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA32F); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureAttachmentId = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0 + 2, - GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, - &textureAttachmentId); - QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - { - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA32F); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture.create()) - qWarning() << "Texture creation failed"; - texture.allocateStorage(); - QVERIFY(texture.isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - { // Check All Faces - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; - - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureIsLayered = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_LAYERED, - &textureIsLayered); - QCOMPARE(textureIsLayered, GL_TRUE); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - { // Check Specific Faces - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color0; - attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; - - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - error = m_func->glGetError(); - QVERIFY(error == 0); - GLint textureFace = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, - &textureFace); - QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); - GLint textureIsLayered = 0; - m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_FRAMEBUFFER_ATTACHMENT_LAYERED, - &textureIsLayered); - QCOMPARE(textureIsLayered, GL_FALSE); - - // Restore state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - } - } - - void bindFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); - - // THEN - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint boundindFBOId = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // WHEN - m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); - - // THEN - error = m_func->glGetError(); - QVERIFY(error == 0); - boundindFBOId = 0; - m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); - QVERIFY(GLuint(boundindFBOId) == fboId); - - // Cleanup - m_func->glDeleteFramebuffers(1, &fboId); - } - - void bindImageTexture() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - - // THEN - QVERIFY(texture.textureId() != 0 && texture.isCreated() && texture.isStorageAllocated()); - - // WHEN - m_glHelper.bindImageTexture(0, - texture.textureId(), - 0, - GL_FALSE, - 0, - GL_READ_WRITE, - GL_RGBA8UI); - - // THEN - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void bindShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Compute, computeShader); - QVERIFY(shaderProgram.link()); - - // WHEN - GLint index = m_func->glGetProgramResourceIndex(shaderProgram.programId(), - GL_SHADER_STORAGE_BLOCK, - "Particles"); - // THEN - GLint binding = -1; - GLenum prop = GL_BUFFER_BINDING; - m_func->glGetProgramResourceiv(shaderProgram.programId(), - GL_SHADER_STORAGE_BLOCK, - index, - 1, &prop, - 4, NULL, &binding); - QCOMPARE(binding, 6); - - // WHEN - m_glHelper.bindShaderStorageBlock(shaderProgram.programId(), index, 1); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - m_func->glGetProgramResourceiv(shaderProgram.programId(), - GL_SHADER_STORAGE_BLOCK, - index, - 1, &prop, - 4, NULL, &binding); - QCOMPARE(binding, 1); - } - - void bindUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); - m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void blendEquation() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLint equation = 0; - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_ADD); - - // WHEN - m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); - - // THEN - m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); - QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); - } - - void blendFunci() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLint destinationRgb = 0; - GLint destinationAlpha = 0; - GLint sourceRgb = 0; - GLint sourceAlpha = 0; - m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 4, &sourceRgb); - m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 4, &destinationRgb); - m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 4, &sourceAlpha); - m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 4, &destinationAlpha); - - // THEN - QCOMPARE(destinationAlpha, GL_ZERO); - QCOMPARE(destinationRgb, GL_ZERO); - QCOMPARE(sourceRgb, GL_ONE); - QCOMPARE(sourceAlpha, GL_ONE); - - // WHEN - m_glHelper.blendFunci(4, GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA); - - m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 4, &sourceRgb); - m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 4, &destinationRgb); - m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 4, &sourceAlpha); - m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 4, &destinationAlpha); - - // THEN - QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA); - QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_ALPHA); - QCOMPARE(sourceRgb, GL_SRC_COLOR); - QCOMPARE(sourceAlpha, GL_SRC_COLOR); - - // Reset default - m_glHelper.blendFunci(4, GL_ONE, GL_ZERO); - } - - void blendFuncSeparatei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLint destinationRgb = 0; - GLint destinationAlpha = 0; - GLint sourceRgb = 0; - GLint sourceAlpha = 0; - m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 2, &sourceRgb); - m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 2, &destinationRgb); - m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 2, &sourceAlpha); - m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 2, &destinationAlpha); - - // THEN - QCOMPARE(destinationAlpha, GL_ZERO); - QCOMPARE(destinationRgb, GL_ZERO); - QCOMPARE(sourceRgb, GL_ONE); - QCOMPARE(sourceAlpha, GL_ONE); - - // WHEN - m_glHelper.blendFuncSeparatei(2, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 2, &sourceRgb); - m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 2, &destinationRgb); - m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 2, &sourceAlpha); - m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 2, &destinationAlpha); - - // THEN - QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA); - QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_COLOR); - QCOMPARE(sourceRgb, GL_SRC_COLOR); - QCOMPARE(sourceAlpha, GL_SRC_ALPHA); - - // Reset default - m_glHelper.blendFunci(4, GL_ONE, GL_ZERO); - } - - void boundFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - // THEN - GLint boundBuffer = 0; - m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); - QCOMPARE(GLuint(boundBuffer), fboId); - - // THEN - QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); - - // Reset state - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void checkFrameBufferComplete() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - Attachment attachment; - attachment.m_point = QRenderTargetOutput::Color1; - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - m_glHelper.bindFrameBufferAttachment(&texture, attachment); - - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - QVERIFY(m_glHelper.checkFrameBufferComplete()); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - } - - void clearBufferf() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - // Create 4 attachments - QOpenGLTexture *textures[4]; - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // Set Draw buffers - GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; - m_func->glDrawBuffers(1, &clearBufferEnum); - - const GLint bufferIndex = 0; // index of the element in the draw buffers - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // WHEN - const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); - m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); - error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - QVector colors(512 * 512); - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - - for (const QVector4D c : colors) { - QVERIFY(c == clearValue1); - } - - // WHEN - const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); - m_glHelper.clearBufferf(bufferIndex, clearValue2); - - // THEN - textures[3]->bind(); - m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); - textures[3]->release(); - for (const QVector4D c : colors) { - QVERIFY(c == clearValue2); - } - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void createFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // WHEN - const GLuint fboId = m_glHelper.createFrameBufferObject(); - - // THEN - QVERIFY(fboId != 0); - - // Restore - m_func->glDeleteFramebuffers(1, &fboId); - } - - void depthMask() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLboolean depthWritingEnabled = false; - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - - // THEN - QVERIFY(depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_FALSE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(!depthWritingEnabled); - - // WHEN - m_glHelper.depthMask(GL_TRUE); - - // THEN - m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); - QVERIFY(depthWritingEnabled); - } - - void depthTest() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_DEPTH_TEST); - m_func->glDepthFunc(GL_LESS); - - // WHEN - m_glHelper.depthTest(GL_LEQUAL); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - GLint depthMode = 0; - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LEQUAL); - - // WHEN - m_glHelper.depthTest(GL_LESS); - QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); - m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); - QCOMPARE(depthMode, GL_LESS); - } - - void disableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_CLIP_DISTANCE0 + 5); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - - // WHEN - m_glHelper.disableClipPlane(5); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); - } - - void disablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glEnablei(GL_BLEND, 2); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); - - // WHEN - m_glHelper.disablei(GL_BLEND, 2); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); - } - - void disablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.disablePrimitiveRestart(); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - } - - void drawBuffers() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); - QOpenGLTexture *textures[4]; - - // Create 4 attachments - for (int i = 0; i < 4; ++i) { - Attachment attachment; - attachment.m_point = static_cast(i); - - QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); - textures[i] = texture; - texture->setSize(512, 512); - texture->setFormat(QOpenGLTexture::RGBA32F); - texture->setMinificationFilter(QOpenGLTexture::Linear); - texture->setMagnificationFilter(QOpenGLTexture::Linear); - texture->setWrapMode(QOpenGLTexture::ClampToEdge); - if (!texture->create()) - qWarning() << "Texture creation failed"; - texture->allocateStorage(); - QVERIFY(texture->isStorageAllocated()); - GLint error = m_func->glGetError(); - QVERIFY(error == 0); - m_glHelper.bindFrameBufferAttachment(texture, attachment); - } - // THEN - GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - // WHEN - GLenum bufferEnum = GL_COLOR_ATTACHMENT4; - m_func->glDrawBuffers(1, &bufferEnum); - - // THEN - GLint enumValue = -1; - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); - - // WHEN - GLint newBufferEnum = 2; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // WHEN - newBufferEnum = 0; - m_glHelper.drawBuffers(1, &newBufferEnum); - - // THEN - m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); - QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); - - // Restore - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glDeleteFramebuffers(1, &fboId); - for (int i = 0; i < 4; ++i) - delete textures[i]; - } - - void enableClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_CLIP_DISTANCE0 + 4); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - - // WHEN - m_glHelper.enableClipPlane(4); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); - } - - void enablei() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisablei(GL_BLEND, 4); - - // THEN - QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); - - // WHEN - m_glHelper.enablei(GL_BLEND, 4); - - // THEN - QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); - } - - void enablePrimitiveRestart() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_PRIMITIVE_RESTART); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - - // WHEN - m_glHelper.enablePrimitiveRestart(883); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); - GLint restartIndex = 0; - m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); - QCOMPARE(restartIndex, 883); - - // Restore - m_func->glDisable(GL_PRIMITIVE_RESTART); - } - - void enableVertexAttribute() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - shaderProgram.bind(); - - // WHEN - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void frontFace() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glFrontFace(GL_CW); - - // THEN - GLint face = 0; - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CW); - - // WHEN - m_glHelper.frontFace(GL_CCW); - - // THEN - m_func->glGetIntegerv(GL_FRONT_FACE, &face); - QCOMPARE(face, GL_CCW); - } - - void getRenderBufferDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint renderBufferId = 0; - m_func->glGenRenderbuffers(1, &renderBufferId); - QVERIFY(renderBufferId != 0); - - // WHEN - m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); - m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); - m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); - const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - - // Restore - m_func->glDeleteRenderbuffers(1, &renderBufferId); - } - - void getTextureDimensions() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLTexture texture(QOpenGLTexture::Target2D); - texture.setSize(512, 512); - texture.setFormat(QOpenGLTexture::RGBA8U); - texture.setMinificationFilter(QOpenGLTexture::Linear); - texture.setMagnificationFilter(QOpenGLTexture::Linear); - texture.create(); - texture.allocateStorage(); - - // WHEN - const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); - - // THEN - QCOMPARE(dimensions, QSize(512, 512)); - } - - void pointSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glEnable(GL_PROGRAM_POINT_SIZE); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - GLfloat size = 0; - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 1.0f); - - // WHEN - m_glHelper.pointSize(false, 0.5f); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); - m_func->glGetFloatv(GL_POINT_SIZE, &size); - QCOMPARE(size, 0.5f); - } - - void maxClipPlaneCount() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLint maxCount = -1; - m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); - - // THEN - QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); - } - - void programUniformBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - // WHEN - const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniformBlocks.size(), 1); - const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); - - QCOMPARE(uniformBlock.m_activeUniformsCount, 1); - QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); - QCOMPARE(uniformBlock.m_binding, 2); - } - - void programAttributesAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeAttributes.size(), 2); - std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_location < b.m_location; }); - - const ShaderAttribute attribute1 = activeAttributes.at(0); - QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); - QCOMPARE(attribute1.m_size, 1); - QCOMPARE(attribute1.m_location, 1); - QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); - - const ShaderAttribute attribute2 = activeAttributes.at(1); - QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); - QCOMPARE(attribute2.m_size, 1); - QCOMPARE(attribute2.m_location, 2); - QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); - } - - void programUniformsAndLocations() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - - // THEN - QCOMPARE(activeUniforms.size(), 4); - std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_location < b.m_location; }); - - const ShaderUniform uniform1 = activeUniforms.at(0); - QCOMPARE(uniform1.m_location, 1); - QCOMPARE(uniform1.m_offset, -1); - QCOMPARE(uniform1.m_blockIndex, -1); - QCOMPARE(uniform1.m_arrayStride, -1); - QCOMPARE(uniform1.m_matrixStride, -1); - QCOMPARE(uniform1.m_size, 1); - QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); - QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); - - const ShaderUniform uniform2 = activeUniforms.at(1); - QCOMPARE(uniform2.m_location, 2); - QCOMPARE(uniform2.m_offset, -1); - QCOMPARE(uniform2.m_blockIndex, -1); - QCOMPARE(uniform2.m_arrayStride, -1); - QCOMPARE(uniform2.m_matrixStride, -1); - QCOMPARE(uniform2.m_size, 1); - QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); - QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); - - const ShaderUniform uniform3 = activeUniforms.at(2); - QCOMPARE(uniform3.m_location, 3); - QCOMPARE(uniform3.m_offset, -1); - QCOMPARE(uniform3.m_blockIndex, -1); - QCOMPARE(uniform3.m_arrayStride, -1); - QCOMPARE(uniform3.m_matrixStride, -1); - QCOMPARE(uniform3.m_size, 1); - QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); - QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); - - const ShaderUniform uniform4 = activeUniforms.at(3); - QCOMPARE(uniform4.m_location, 4); - QCOMPARE(uniform4.m_offset, -1); - QCOMPARE(uniform4.m_blockIndex, -1); - QCOMPARE(uniform4.m_arrayStride, -1); - QCOMPARE(uniform4.m_matrixStride, -1); - QCOMPARE(uniform4.m_size, 1); - QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); - QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); - } - - void programShaderStorageBlock() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Compute, computeShader); - QVERIFY(shaderProgram.link()); - - // WHEN - const QVector activeShaderStorageBlocks = m_glHelper.programShaderStorageBlocks(shaderProgram.programId()); - - // THEN - QVERIFY(activeShaderStorageBlocks.size() == 1); - ShaderStorageBlock block = activeShaderStorageBlocks.first(); - QCOMPARE(block.m_name, QStringLiteral("Particles")); - QCOMPARE(block.m_activeVariablesCount, 3); - QCOMPARE(block.m_index, 0); - QCOMPARE(block.m_binding, 6); - QCOMPARE(block.m_size, (4 + 4 + 4) * 4); - } - - void releaseFrameBufferObject() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint fboId; - m_func->glGenFramebuffers(1, &fboId); - - // THEN - QVERIFY(fboId != 0); - - // WHEN - m_glHelper.releaseFrameBufferObject(fboId); - - // THEN - QVERIFY(!m_func->glIsFramebuffer(fboId)); - } - - void setMSAAEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_MULTISAMPLE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); - - // WHEN - m_glHelper.setMSAAEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); - } - - void setAlphaCoverageEnabled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - - // WHEN - m_glHelper.setAlphaCoverageEnabled(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); - } - - void setClipPlane() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - // Deprecated in GL 4 - } - - void setSeamlessCubemap() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - - void setVerticesPerPatch() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(true); - - // THEN - QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - - // WHEN - m_glHelper.setSeamlessCubemap(false); - - // THEN - QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); - } - - void supportsFeature() - { - for (int i = 0; i <= GraphicsHelperInterface::Fences; ++i) - QVERIFY(m_glHelper.supportsFeature(static_cast(i))); - } - - -#define ADD_UNIFORM_ENTRY(FragShader, Type, Location, ComponentSize, ExpectedRawSize) \ - QTest::newRow(#FragShader"_"#Type) << FragShader << Type << Location << ComponentSize << ExpectedRawSize; - - void uniformsByteSize_data() - { - QTest::addColumn("fragShader"); - QTest::addColumn("type"); - QTest::addColumn("location"); - QTest::addColumn("componentSize"); - QTest::addColumn("expectedByteSize"); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT, 1, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC2, 2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC3, 3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC4, 4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT, 1, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC2, 2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC3, 3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC4, 4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT, 1, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC2, 2, 1, 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC3, 3, 1, 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC4, 4, 1, 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2, 1, 1, 4 * 2 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x3, 2, 1, 4 * 2 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x2, 3, 1, 4 * 3 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x4, 4, 1, 4 * 2 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x2, 5, 1, 4 * 4 * 2); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3, 6, 1, 4 * 3 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x4, 7, 1, 4 * 3 * 4); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x3, 8, 1, 4 * 4 * 3); - ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4, 9, 1, 4 * 4 * 4); - - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_1D, 1, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D, 2, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_ARRAY, 3, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_3D, 4, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_CUBE, 5, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_RECT, 6, 1, 4); - - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_1D, 1, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D, 2, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_ARRAY, 3, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_3D, 4, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_CUBE, 5, 1, 4); - ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_RECT, 6, 1, 4); - } - - void uniformsByteSize() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QFETCH(QByteArray, fragShader); - QFETCH(int, type); - QFETCH(int, location); - QFETCH(int, componentSize); - QFETCH(int, expectedByteSize); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); - QVERIFY(shaderProgram.link()); - - // WHEN - const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); - ShaderUniform matchingUniform; - for (const ShaderUniform &u : activeUniforms) { - if (u.m_location == location) { - matchingUniform = u; - break; - } - } - - // THEN - QCOMPARE(matchingUniform.m_location, location); - QCOMPARE(matchingUniform.m_type, GLuint(type)); - QCOMPARE(matchingUniform.m_size, componentSize); - - // WHEN - const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); - - // THEN - QCOMPARE(expectedByteSize, computedRawByteSize); - - // Restore - m_func->glUseProgram(0); - } - - void useProgram() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); - - // THEN - QVERIFY(shaderProgram.link()); - - GLint currentProg = 0; - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - - // WHEN - m_glHelper.useProgram(shaderProgram.programId()); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QCOMPARE(GLuint(currentProg), shaderProgram.programId()); - - // WHEN - m_glHelper.useProgram(0); - - // THEN - m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); - QVERIFY(currentProg == 0); - } - - void vertexAttribDivisor() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - } - - void vertexAttributePointer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLVertexArrayObject vao; - vao.create(); - QOpenGLVertexArrayObject::Binder binder(&vao); - - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); - QVERIFY(shaderProgram.link()); - - GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); - GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); - GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); - GLint texCoordScaleLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoordScale"); - - const int vertexCount = 99; - QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); - positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - positionBuffer.create(); - positionBuffer.bind(); - positionBuffer.allocate(vertexCount * sizeof(QVector3D)); - - QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); - texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - texCoordBuffer.create(); - texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); - - QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); - colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - colorIndexBuffer.create(); - colorIndexBuffer.allocate(vertexCount * sizeof(int)); - - QOpenGLBuffer scaleBuffer(QOpenGLBuffer::VertexBuffer); - scaleBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); - scaleBuffer.create(); - scaleBuffer.allocate(vertexCount * sizeof(double)); - - // WHEN - shaderProgram.bind(); - positionBuffer.bind(); - m_glHelper.enableVertexAttributeArray(positionLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); - - texCoordBuffer.bind(); - m_glHelper.enableVertexAttributeArray(texCoordLocation); - m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); - - colorIndexBuffer.bind(); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); - - scaleBuffer.bind(); - m_glHelper.enableVertexAttributeArray(colorIndexLocation); - m_glHelper.vertexAttributePointer(GL_DOUBLE, texCoordScaleLocation, 1, GL_DOUBLE, GL_TRUE, 0, 0); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void glUniform1fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat value = 883.0f; - m_glHelper.glUniform1fv(1, 1, &value); - - // THEN - GLfloat setValue = 0.0f; - m_func->glGetUniformfv(shaderProgram.programId(), 1, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[2] = { 383.0f, 427.0f }; - m_glHelper.glUniform2fv(2, 1, values); - - // THEN - GLfloat setValues[2] = { 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 2, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; - m_glHelper.glUniform3fv(3, 1, values); - - // THEN - GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 3, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - m_glHelper.glUniform4fv(4, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 4, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(setValues[i], values[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint value = 883; - m_glHelper.glUniform1iv(1, 1, &value); - - // THEN - GLint setValue = 0; - m_func->glGetUniformiv(shaderProgram.programId(), 1, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[2] = { 383, 427 }; - m_glHelper.glUniform2iv(2, 1, values); - - // THEN - GLint setValues[2] = { 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), 2, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[3] = { 572, 1340, 1584 }; - m_glHelper.glUniform3iv(3, 1, values); - - // THEN - GLint setValues[3] = { 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), 3, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4iv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLint values[4] = { 454, 350, 883, 355 }; - m_glHelper.glUniform4iv(4, 1, values); - - // THEN - GLint setValues[4] = { 0, 0, 0, 0 }; - m_func->glGetUniformiv(shaderProgram.programId(), 4, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform1uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint value = 883U; - m_glHelper.glUniform1uiv(1, 1, &value); - - // THEN - GLuint setValue = 0U; - m_func->glGetUniformuiv(shaderProgram.programId(), 1, &setValue); - QCOMPARE(value, setValue); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform2uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[2] = { 383U, 427U }; - m_glHelper.glUniform2uiv(2, 1, values); - - // THEN - GLuint setValues[2] = { 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), 2, setValues); - for (int i = 0; i < 2; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform3uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[3] = { 572U, 1340U, 1584U }; - m_glHelper.glUniform3uiv(3, 1, values); - - // THEN - GLuint setValues[3] = { 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), 3, setValues); - for (int i = 0; i < 3; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniform4uiv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLuint values[4] = { 454U, 350U, 883U, 355U }; - m_glHelper.glUniform4uiv(4, 1, values); - - // THEN - GLuint setValues[4] = { 0U, 0U, 0U, 0U }; - m_func->glGetUniformuiv(shaderProgram.programId(), 4, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; - m_glHelper.glUniformMatrix2fv(1, 1, values); - - // THEN - GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 1, setValues); - for (int i = 0; i < 4; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; - m_glHelper.glUniformMatrix3fv(6, 1, values); - - // THEN - GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 6, setValues); - for (int i = 0; i < 9; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; - m_glHelper.glUniformMatrix4fv(9, 1, values); - - // THEN - GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 9, setValues); - for (int i = 0; i < 16; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - m_glHelper.glUniformMatrix2x3fv(2, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 2, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - m_glHelper.glUniformMatrix3x2fv(3, 1, values); - - // THEN - GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 3, setValues); - for (int i = 0; i < 6; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix2x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - m_glHelper.glUniformMatrix2x4fv(4, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 4, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x2fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - m_glHelper.glUniformMatrix4x2fv(5, 1, values); - - // THEN - GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 5, setValues); - for (int i = 0; i < 8; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix3x4fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f,}; - m_glHelper.glUniformMatrix3x4fv(7, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 7, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - void glUniformMatrix4x3fv() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - QOpenGLShaderProgram shaderProgram; - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); - shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); - QVERIFY(shaderProgram.link()); - - // WHEN - m_func->glUseProgram(shaderProgram.programId()); - GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; - m_glHelper.glUniformMatrix4x3fv(8, 1, values); - - // THEN - GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; - m_func->glGetUniformfv(shaderProgram.programId(), 8, setValues); - for (int i = 0; i < 12; ++i) - QCOMPARE(values[i], setValues[i]); - - // Restore - m_func->glUseProgram(0); - } - - - void blitFramebuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - // GIVEN - GLuint fbos[2]; - GLuint fboTextures[2]; - - m_func->glGenFramebuffers(2, fbos); - m_func->glGenTextures(2, fboTextures); - - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); - m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 10, 10, true); - m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); - - m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); - m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - m_func->glBindTexture(GL_TEXTURE_2D, 0); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); - - GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); - m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); - - status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); - QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); - - m_func->glEnable(GL_MULTISAMPLE); - m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); - m_func->glClear(GL_COLOR_BUFFER_BIT); - m_func->glDisable(GL_MULTISAMPLE); - - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); - - // WHEN - m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); - - GLuint result[10*10]; - m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); - - // THEN - GLuint v = (0.2f) * 255; - v = v | (v<<8) | (v<<16) | (v<<24); - for (GLuint value : result) { - QCOMPARE(value, v); - } - m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - m_func->glDeleteFramebuffers(2, fbos); - m_func->glDeleteTextures(2, fboTextures); - } - -#define ADD_GL_TYPE_ENTRY(Type, Expected) \ - QTest::newRow(#Type) << Type << Expected; - - void uniformTypeFromGLType_data() - { - QTest::addColumn("glType"); - QTest::addColumn("expected"); - - ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); - ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); - ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); - ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); - ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); - ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); - ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); - ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); - ADD_GL_TYPE_ENTRY(GL_IMAGE_1D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_2D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_3D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_RECT, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_BUFFER, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_1D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D, UniformType::Image); ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_3D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_RECT, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_BUFFER, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_3D, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_RECT, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_BUFFER, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image); - ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); - } - - void uniformTypeFromGLType() - { - // GIVEN - QFETCH(int, glType); - QFETCH(UniformType, expected); - - // WHEN - UniformType computed = m_glHelper.uniformTypeFromGLType(glType); - - // THEN - QCOMPARE(computed, expected); - } - - void drawBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.drawBuffer(GL_FRONT); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // THEN - GLint p; - m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void readBuffer() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - m_glHelper.readBuffer(GL_FRONT); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_READ_BUFFER, &p); - QCOMPARE(p, GL_FRONT); - } - - void fenceSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - // THEN - QVERIFY(sync != nullptr); - QCOMPARE(m_func->glIsSync(sync), GL_TRUE); - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void clientWaitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - QElapsedTimer t; - t.start(); - - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - - m_glHelper.clientWaitSync(sync, 1000000); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - qDebug() << t.nsecsElapsed(); - } - - void waitSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - } - - void wasSyncSignaled() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_func->glFlush(); - m_glHelper.waitSync(sync); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - - // Shouldn't loop forever - while (!m_glHelper.wasSyncSignaled(sync)) - ; - } - - void deleteSync() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); - - m_func->glGetError(); - - // WHEN - GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); - m_glHelper.clientWaitSync(sync, GLuint64(-1)); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); - - // WHEN - m_glHelper.deleteSync(sync); - - // THEN - QCOMPARE(m_func->glIsSync(sync), GL_FALSE); - } - - void rasterMode() - { - if (!m_initializationSuccessful) - QSKIP("Initialization failed, OpenGL 4.3 functions not supported"); - - m_func->glGetError(); - m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); - - // THEN - const GLint error = m_func->glGetError(); - QVERIFY(error == 0); - GLint p; - m_func->glGetIntegerv(GL_POLYGON_MODE, &p); - QCOMPARE(p, GL_LINE); - } - -private: - QScopedPointer m_window; - QOpenGLContext m_glContext; - GraphicsHelperGL4 m_glHelper; - QOpenGLFunctions_4_3_Core *m_func = nullptr; - bool m_initializationSuccessful = false; -}; - -#endif - -int main(int argc, char *argv[]) -{ -#ifdef TEST_SHOULD_BE_PERFORMED - QGuiApplication app(argc, argv); - app.setAttribute(Qt::AA_Use96Dpi, true); - tst_GraphicsHelperGL4 tc; - QTEST_SET_MAIN_SOURCE_PATH - return QTest::qExec(&tc, argc, argv); -#endif - return 0; -} - -#ifdef TEST_SHOULD_BE_PERFORMED -#include "tst_graphicshelpergl4.moc" -#endif diff --git a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp index 255ff5ea8..1ffec30ae 100644 --- a/tests/auto/render/layerfiltering/tst_layerfiltering.cpp +++ b/tests/auto/render/layerfiltering/tst_layerfiltering.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/auto/render/materialparametergathererjob/materialparametergathererjob.pro b/tests/auto/render/materialparametergathererjob/materialparametergathererjob.pro deleted file mode 100644 index ac68b8248..000000000 --- a/tests/auto/render/materialparametergathererjob/materialparametergathererjob.pro +++ /dev/null @@ -1,11 +0,0 @@ -TEMPLATE = app - -TARGET = tst_materialparametergathererjob - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_materialparametergathererjob.cpp - -include(../commons/commons.pri) diff --git a/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp b/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp deleted file mode 100644 index 236faa8f0..000000000 --- a/tests/auto/render/materialparametergathererjob/tst_materialparametergathererjob.cpp +++ /dev/null @@ -1,799 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class TestAspect : public Qt3DRender::QRenderAspect -{ -public: - TestAspect(Qt3DCore::QNode *root) - : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) - , m_jobManager(new Qt3DCore::QAspectJobManager()) - { - Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); - QRenderAspect::onRegistered(); - - QVector nodes; - Qt3DCore::QNodeVisitor v; - v.traverse(root, [&nodes](Qt3DCore::QNode *node) { - Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); - d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); - d->m_hasBackendNode = true; - nodes << node; - }); - - for (const auto node: nodes) - d_func()->createBackendNode({ - node->id(), - Qt3DCore::QNodePrivate::get(node)->m_typeInfo, - Qt3DCore::NodeTreeChange::Added, - node - }); - - const auto handles = nodeManagers()->techniqueManager()->activeHandles(); - for (const auto &handle: handles) { - Render::Technique *technique = nodeManagers()->techniqueManager()->data(handle); - technique->setCompatibleWithRenderer(true); - } - } - - ~TestAspect() - { - QRenderAspect::onUnregistered(); - } - - Qt3DRender::Render::NodeManagers *nodeManagers() const - { - return d_func()->m_renderer->nodeManagers(); - } - - void initializeRenderer() - { - d_func()->m_renderer->initialize(); - } - - Render::MaterialParameterGathererJobPtr materialGathererJob() const - { - Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); - job->setNodeManagers(nodeManagers()); - return job; - } - - void onRegistered() { QRenderAspect::onRegistered(); } - void onUnregistered() { QRenderAspect::onUnregistered(); } - -private: - QScopedPointer m_jobManager; -}; - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -namespace { - -class TestMaterial : public Qt3DRender::QMaterial -{ - Q_OBJECT -public: - explicit TestMaterial(Qt3DCore::QNode *parent = nullptr) - : Qt3DRender::QMaterial(parent) - , m_effect(new Qt3DRender::QEffect()) - , m_gl3Technique(new Qt3DRender::QTechnique()) - , m_gl2Technique(new Qt3DRender::QTechnique()) - , m_es2Technique(new Qt3DRender::QTechnique()) - , m_gl3Pass(new Qt3DRender::QRenderPass()) - , m_gl2Pass(new Qt3DRender::QRenderPass()) - , m_es2Pass(new Qt3DRender::QRenderPass()) - , m_gl3Program(new Qt3DRender::QShaderProgram()) - , m_gl2es2Program(new Qt3DRender::QShaderProgram()) - { - m_gl3Pass->setShaderProgram(m_gl3Program); - m_gl2Pass->setShaderProgram(m_gl2es2Program); - m_es2Pass->setShaderProgram(m_gl2es2Program); - - m_gl3Technique->addRenderPass(m_gl3Pass); - m_gl2Technique->addRenderPass(m_gl2Pass); - m_es2Technique->addRenderPass(m_es2Pass); - - m_effect->addTechnique(m_gl3Technique); - m_effect->addTechnique(m_gl2Technique); - m_effect->addTechnique(m_es2Technique); - - setEffect(m_effect); - } - - Qt3DRender::QTechnique *gl3Technique() const { return m_gl3Technique; } - Qt3DRender::QTechnique *gl2Technique() const { return m_gl2Technique; } - Qt3DRender::QTechnique *es2Technique() const { return m_es2Technique; } - - Qt3DRender::QRenderPass *gl3Pass() const { return m_gl3Pass; } - Qt3DRender::QRenderPass *gl2Pass() const { return m_gl2Pass; } - Qt3DRender::QRenderPass *es2Pass() const { return m_es2Pass; } - - Qt3DRender::QShaderProgram *gl3Shader() const { return m_gl3Program; } - Qt3DRender::QShaderProgram *gl2shader() const { return m_gl2es2Program; } - Qt3DRender::QShaderProgram *es2Shader() const { return m_gl2es2Program; } - -private: - Qt3DRender::QEffect *m_effect; - Qt3DRender::QTechnique *m_gl3Technique; - Qt3DRender::QTechnique *m_gl2Technique; - Qt3DRender::QTechnique *m_es2Technique; - Qt3DRender::QRenderPass *m_gl3Pass; - Qt3DRender::QRenderPass *m_gl2Pass; - Qt3DRender::QRenderPass *m_es2Pass; - Qt3DRender::QShaderProgram *m_gl3Program; - Qt3DRender::QShaderProgram *m_gl2es2Program; -}; - -Qt3DRender::QViewport *viewportFrameGraph() -{ - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - return viewport; -} - -Qt3DRender::QTechniqueFilter *techniqueFilterFrameGraph() -{ - Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(); - return techniqueFilter; -} - -Qt3DRender::QRenderPassFilter *renderPassFilter() -{ - Qt3DRender::QRenderPassFilter *passFilter = new Qt3DRender::QRenderPassFilter(); - return passFilter; -} - -Qt3DCore::QEntity *buildScene(Qt3DRender::QFrameGraphNode *frameGraph, Qt3DRender::QMaterial *material = nullptr) -{ - Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); - - // FrameGraph - Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); - renderSettings->setActiveFrameGraph(frameGraph); - root->addComponent(renderSettings); - - // Scene - for (int i = 0; i < 10; i++) { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - if (material != nullptr) - e->addComponent(material); - e->setParent(root); - } - - return root; -} - -} // anonymous - -class tst_MaterialParameterGatherer : public QObject -{ - Q_OBJECT -private Q_SLOTS: - - void checkRunNoHandlesNoTechniqueFilterNoPassFilter() - { - // GIVEN - Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph()); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 0); - - // WHEN - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); - } - - void checkRunSelectAllNoTechniqueFilterNoPassFilter() - { - // GIVEN - TestMaterial material; - Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - } - - void checkRunDisabledMaterial() - { - // GIVEN - TestMaterial material; - material.setEnabled(false); - Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); - } - - void checkRunSelectAllTechniqueFilterWithNoFilterNoPassFilter() - { - // GIVEN - Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); - - TestMaterial material; - - Qt3DRender::QFilterKey techniqueFilterKey; - techniqueFilterKey.setName(QStringLiteral("renderingStyle")); - techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); - - material.gl2Technique()->addFilterKey(&techniqueFilterKey); - material.gl3Technique()->addFilterKey(&techniqueFilterKey); - material.es2Technique()->addFilterKey(&techniqueFilterKey); - - Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); - QVERIFY(backendTechniqueFilter != nullptr); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - } - - void checkRunSelectAllTechniqueFilterWithIncompatibleFilterNoPassFilter() - { - // GIVEN - Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); - TestMaterial material; - - Qt3DRender::QFilterKey techniqueFilterFilterKey; - techniqueFilterFilterKey.setName(QStringLiteral("renderingStyle")); - techniqueFilterFilterKey.setValue(QVariant(QStringLiteral("forward"))); - - Qt3DRender::QFilterKey techniqueFilterKey; - techniqueFilterKey.setName(QStringLiteral("renderingStyle")); - techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); - - frameGraphFilter->addMatch(&techniqueFilterFilterKey); - - material.gl2Technique()->addFilterKey(&techniqueFilterKey); - material.gl3Technique()->addFilterKey(&techniqueFilterKey); - material.es2Technique()->addFilterKey(&techniqueFilterKey); - - Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); - QVERIFY(backendTechniqueFilter != nullptr); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); - } - - void checkRunSelectAllTechniqueFilterWithCompatibleFilterNoPassFilter() - { - // GIVEN - Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); - TestMaterial material; - - Qt3DRender::QFilterKey techniqueFilterKey; - techniqueFilterKey.setName(QStringLiteral("renderingStyle")); - techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); - - frameGraphFilter->addMatch(&techniqueFilterKey); - - material.gl2Technique()->addFilterKey(&techniqueFilterKey); - material.gl3Technique()->addFilterKey(&techniqueFilterKey); - material.es2Technique()->addFilterKey(&techniqueFilterKey); - - Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); - QVERIFY(backendTechniqueFilter != nullptr); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - } - - void checkRunSelectAllNoTechniqueFilterPassFilterWithNoFilter() - { - // GIVEN - Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); - TestMaterial material; - - Qt3DRender::QFilterKey passFilterKey; - passFilterKey.setName(QStringLiteral("renderingStyle")); - passFilterKey.setValue(QVariant(QStringLiteral("backward"))); - - material.gl3Pass()->addFilterKey(&passFilterKey); - material.gl2Pass()->addFilterKey(&passFilterKey); - material.es2Pass()->addFilterKey(&passFilterKey); - - Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); - QVERIFY(backendPassFilter != nullptr); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendPassFilter); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - } - - void checkRunSelectAllNoTechniqueFilterPassFilterWithIncompatibleFilter() - { - // GIVEN - Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); - TestMaterial material; - - Qt3DRender::QFilterKey passFilterFilterKey; - passFilterFilterKey.setName(QStringLiteral("renderingStyle")); - passFilterFilterKey.setValue(QVariant(QStringLiteral("forward"))); - - Qt3DRender::QFilterKey passFilterKey; - passFilterKey.setName(QStringLiteral("renderingStyle")); - passFilterKey.setValue(QVariant(QStringLiteral("backward"))); - - frameGraphFilter->addMatch(&passFilterFilterKey); - - material.gl3Pass()->addFilterKey(&passFilterKey); - material.gl2Pass()->addFilterKey(&passFilterKey); - material.es2Pass()->addFilterKey(&passFilterKey); - - Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - - testAspect.initializeRenderer(); - - // THEN - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); - QVERIFY(backendPassFilter != nullptr); - - // WHEN - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendPassFilter); - gatherer->run(); - - // THEN - QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); - } - - void checkParameterPriorityGathering() - { - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - techniqueFilterFG->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::red)))); - - auto renderPassParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); - - renderPassFG->addParameter(renderPassParameter); - material.addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::green)))); - material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); - - auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); - - material.gl3Technique()->addParameter(techniqueParam); - material.gl2Technique()->addParameter(techniqueParam); - material.es2Technique()->addParameter(techniqueParam); - - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> RenderPassFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(renderPassParameter->id())); - } - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - auto techniqueFilterParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); - techniqueFilterFG->addParameter(techniqueFilterParameter); - - material.addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::green)))); - material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); - - auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); - - material.gl3Technique()->addParameter(techniqueParam); - material.gl2Technique()->addParameter(techniqueParam); - material.es2Technique()->addParameter(techniqueParam); - - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> TechniqueFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueFilterParameter->id())); - } - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - auto materialParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); - - material.addParameter(materialParameter); - material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); - - auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); - - material.gl3Technique()->addParameter(techniqueParam); - material.gl2Technique()->addParameter(techniqueParam); - material.es2Technique()->addParameter(techniqueParam); - - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> TechniqueFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(materialParameter->id())); - } - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - auto effectParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); - - material.effect()->addParameter(effectParameter); - - auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); - - material.gl3Technique()->addParameter(techniqueParam); - material.gl2Technique()->addParameter(techniqueParam); - material.es2Technique()->addParameter(techniqueParam); - - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> TechniqueFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(effectParameter->id())); - } - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); - - material.gl3Technique()->addParameter(techniqueParam); - material.gl2Technique()->addParameter(techniqueParam); - material.es2Technique()->addParameter(techniqueParam); - - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> TechniqueFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueParam->id())); - } - { - // GIVEN - Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); - Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); - - renderPassFG->setParent(techniqueFilterFG); - - TestMaterial material; - - Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); - - // WHEN - auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); - - material.gl3Pass()->addParameter(passParam); - material.gl2Pass()->addParameter(passParam); - material.es2Pass()->addParameter(passParam); - - Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); - testAspect.initializeRenderer(); - - QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); - Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); - Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); - QVERIFY(backendTechniqueFilter != nullptr); - QVERIFY(backendRenderPassFilter != nullptr); - - gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); - gatherer->setRenderPassFilter(backendRenderPassFilter); - gatherer->setTechniqueFilter(backendTechniqueFilter); - gatherer->run(); - - // THEN -> TechniqueFilter wins - QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); - QCOMPARE(passParameterData.size(), 1); - - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); - - QCOMPARE(data.parameterInfo.size(), 1); - QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(passParam->id())); - } - } -}; - -QTEST_MAIN(tst_MaterialParameterGatherer) - -#include "tst_materialparametergathererjob.moc" diff --git a/tests/auto/render/opengl/computecommand/computecommand.pro b/tests/auto/render/opengl/computecommand/computecommand.pro new file mode 100644 index 000000000..38515059a --- /dev/null +++ b/tests/auto/render/opengl/computecommand/computecommand.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_computecommand + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_computecommand.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/computecommand/tst_computecommand.cpp b/tests/auto/render/opengl/computecommand/tst_computecommand.cpp new file mode 100644 index 000000000..80cbfb090 --- /dev/null +++ b/tests/auto/render/opengl/computecommand/tst_computecommand.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qbackendnodetester.h" +#include "testrenderer.h" +#include "testpostmanarbiter.h" + + +// tst_Renderer is a friend class of Renderer +class tst_Renderer : public Qt3DRender::Render::Renderer +{ +public: + tst_Renderer() + : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous) + {} + + ~tst_Renderer() { + shutdown(); + } +}; + + +class tst_ComputeCommand : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkDisablesFrontend() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManager; + tst_Renderer renderer; + TestArbiter arbiter; + + Qt3DCore::QAspectManager manager; + Qt3DCore::QScene scene; + + Qt3DCore::QEntity rootEntity; + Qt3DCore::QNodePrivate::get(&rootEntity)->setScene(&scene); + + Qt3DRender::QComputeCommand computeCommand; + Qt3DRender::Render::ComputeCommand *backendComputeCommand = nullptr; + + renderer.setNodeManagers(&nodeManager); + + // WHEN + computeCommand.setParent(&rootEntity); + // RootEntity is the entry point to retrieve the scene instance for lookups + manager.setRootEntity(&rootEntity, {}); + + // THEN + QVERIFY(scene.lookupNode(computeCommand.id()) != nullptr); + + // WHEN + auto handle = nodeManager.computeJobManager()->getOrAcquireHandle(computeCommand.id()); + backendComputeCommand = nodeManager.computeJobManager()->data(handle); + + // WHEN + computeCommand.setWorkGroupX(256); + computeCommand.setWorkGroupY(512); + computeCommand.setWorkGroupZ(128); + computeCommand.setRunType(Qt3DRender::QComputeCommand::Manual); + computeCommand.trigger(1); + + Qt3DCore::QBackendNodePrivate::get(backendComputeCommand)->setArbiter(&arbiter); + backendComputeCommand->setRenderer(&renderer); + simulateInitializationSync(&computeCommand, backendComputeCommand); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(),1); + QCOMPARE(backendComputeCommand->isEnabled(), true); + QCOMPARE(computeCommand.isEnabled(), true); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); + + // WHEN + backendComputeCommand->updateFrameCount(); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(), 0); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), true); + + + // Still enabled as we have yet to notify the fronted + QCOMPARE(backendComputeCommand->isEnabled(), true); + QCOMPARE(computeCommand.isEnabled(), true); + + // WHEN + renderer.jobsDone(&manager); // so Renderer::sendDisablesToFrontend gets called + + // THEN + QCOMPARE(computeCommand.isEnabled(), false); + QCOMPARE(backendComputeCommand->hasReachedFrameCount(), false); + + // WHEN + backendComputeCommand->syncFromFrontEnd(&computeCommand, false); + + // THEN + QCOMPARE(backendComputeCommand->frameCount(), 0); + QCOMPARE(backendComputeCommand->isEnabled(), false); + } +}; + +QTEST_MAIN(tst_ComputeCommand) + +#include "tst_computecommand.moc" diff --git a/tests/auto/render/opengl/filtercompatibletechniquejob/BLACKLIST b/tests/auto/render/opengl/filtercompatibletechniquejob/BLACKLIST new file mode 100644 index 000000000..7cbc7c4c0 --- /dev/null +++ b/tests/auto/render/opengl/filtercompatibletechniquejob/BLACKLIST @@ -0,0 +1,6 @@ +#[checkRunRendererRunning] +windows-7 +windows-7sp1 +#QTBUG-64271 +# Offscreen platform does not support OpenGL context creation +b2qt diff --git a/tests/auto/render/opengl/filtercompatibletechniquejob/filtercompatibletechniquejob.pro b/tests/auto/render/opengl/filtercompatibletechniquejob/filtercompatibletechniquejob.pro new file mode 100644 index 000000000..5d533839c --- /dev/null +++ b/tests/auto/render/opengl/filtercompatibletechniquejob/filtercompatibletechniquejob.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_filtercompatibletechniquejob + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_filtercompatibletechniquejob.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp new file mode 100644 index 000000000..8b9390340 --- /dev/null +++ b/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class TestAspect : public Qt3DRender::QRenderAspect +{ +public: + TestAspect(Qt3DCore::QNode *root) + : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) + , m_jobManager(new Qt3DCore::QAspectJobManager()) + , m_window(new QWindow()) + , m_contextCreationSuccessful(false) + { + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + m_window->create(); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to make OpenGL context current"; + return; + } + + m_contextCreationSuccessful = true; + + Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); + QRenderAspect::onRegistered(); + + QVector nodes; + Qt3DCore::QNodeVisitor v; + v.traverse(root, [&nodes](Qt3DCore::QNode *node) { + Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); + d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); + d->m_hasBackendNode = true; + nodes << node; + }); + + for (const auto node: nodes) + d_func()->createBackendNode({ + node->id(), + Qt3DCore::QNodePrivate::get(node)->m_typeInfo, + Qt3DCore::NodeTreeChange::Added, + node + }); + } + + ~TestAspect() + { + if (m_contextCreationSuccessful) + QRenderAspect::onUnregistered(); + } + + Qt3DRender::Render::NodeManagers *nodeManagers() const + { + return d_func()->m_renderer + ? d_func()->m_renderer->nodeManagers() : nullptr; + } + + bool contextCreationSuccessful() const + { + return m_contextCreationSuccessful; + } + + void initializeRenderer() + { + renderer()->setOpenGLContext(&m_glContext); + d_func()->m_renderer->initialize(); + renderer()->submissionContext()->beginDrawing(m_window.data()); + } + + Render::Renderer *renderer() const + { + return static_cast(d_func()->m_renderer); + } + + void onRegistered() { QRenderAspect::onRegistered(); } + void onUnregistered() { QRenderAspect::onUnregistered(); } + +private: + QScopedPointer m_jobManager; + QScopedPointer m_window; + QOpenGLContext m_glContext; + bool m_contextCreationSuccessful; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +namespace { + +Qt3DCore::QEntity *buildTestScene() +{ + Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); + + // FrameGraph + Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); + renderSettings->setActiveFrameGraph(new Qt3DRender::QViewport()); + root->addComponent(renderSettings); + + // Scene + Qt3DRender::QTechnique *gl2Technique = new Qt3DRender::QTechnique(root); + gl2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + gl2Technique->graphicsApiFilter()->setMajorVersion(2); + gl2Technique->graphicsApiFilter()->setMinorVersion(0); + gl2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + + Qt3DRender::QTechnique *gl3Technique = new Qt3DRender::QTechnique(root); + gl3Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGL); + gl3Technique->graphicsApiFilter()->setMajorVersion(3); + gl3Technique->graphicsApiFilter()->setMinorVersion(2); + gl3Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::CoreProfile); + + Qt3DRender::QTechnique *es2Technique = new Qt3DRender::QTechnique(root); + es2Technique->graphicsApiFilter()->setApi(Qt3DRender::QGraphicsApiFilter::OpenGLES); + es2Technique->graphicsApiFilter()->setMajorVersion(2); + es2Technique->graphicsApiFilter()->setMinorVersion(0); + es2Technique->graphicsApiFilter()->setProfile(Qt3DRender::QGraphicsApiFilter::NoProfile); + + return root; +} + +} // anonymous + +class tst_FilterCompatibleTechniqueJob : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void initTestCase() + { + QSurfaceFormat format; +#ifdef QT_OPENGL_ES_2 + format.setRenderableType(QSurfaceFormat::OpenGLES); +#else + if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { + format.setVersion(4, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + } +#endif + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(format); + } + + void checkInitialState() + { + // GIVEN + Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; + + // THEN + QVERIFY(backendFilterCompatibleTechniqueJob.manager() == nullptr); + QVERIFY(backendFilterCompatibleTechniqueJob.renderer() == nullptr); + + // WHEN + Qt3DRender::Render::TechniqueManager techniqueManager; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + backendFilterCompatibleTechniqueJob.setManager(&techniqueManager); + backendFilterCompatibleTechniqueJob.setRenderer(&renderer); + + // THEN + QCOMPARE(backendFilterCompatibleTechniqueJob.manager(), &techniqueManager); + QCOMPARE(backendFilterCompatibleTechniqueJob.renderer(), &renderer); + + renderer.shutdown(); + } + + void checkRunRendererRunning() + { + // GIVEN + Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; + Qt3DRender::TestAspect testAspect(buildTestScene()); + + const bool unableToCreateContext = !testAspect.contextCreationSuccessful(); + + if (unableToCreateContext) + QSKIP("Initialization failed, unable to create GL context"); + + // WHEN + Qt3DRender::Render::NodeManagers *nodeManagers = testAspect.nodeManagers(); + QVERIFY(nodeManagers); + Qt3DRender::Render::TechniqueManager *techniqueManager = nodeManagers->techniqueManager(); + QVERIFY(techniqueManager); + backendFilterCompatibleTechniqueJob.setManager(techniqueManager); + backendFilterCompatibleTechniqueJob.setRenderer(testAspect.renderer()); + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.renderer()->isRunning(), true); + QCOMPARE(testAspect.renderer()->submissionContext()->isInitialized(), true); + const QVector handles = testAspect.nodeManagers()->techniqueManager()->activeHandles(); + QCOMPARE(handles.size(), 3); + + // WHEN + backendFilterCompatibleTechniqueJob.run(); + + // THEN -> empty if job ran properly + const QVector dirtyTechniquesId = testAspect.nodeManagers()->techniqueManager()->takeDirtyTechniques(); + QCOMPARE(dirtyTechniquesId.size(), 0); + + // Check at least one technique is valid + bool foundValid = false; + for (const auto handle: handles) { + Qt3DRender::Render::Technique *technique = testAspect.nodeManagers()->techniqueManager()->data(handle); + foundValid |= technique->isCompatibleWithRenderer(); + } + QCOMPARE(foundValid, true); + } +}; + +QTEST_MAIN(tst_FilterCompatibleTechniqueJob) + +#include "tst_filtercompatibletechniquejob.moc" diff --git a/tests/auto/render/opengl/glshadermanager/glshadermanager.pro b/tests/auto/render/opengl/glshadermanager/glshadermanager.pro new file mode 100644 index 000000000..dc96ab3bb --- /dev/null +++ b/tests/auto/render/opengl/glshadermanager/glshadermanager.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_glshadermanager + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_glshadermanager.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp b/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp new file mode 100644 index 000000000..83420af3b --- /dev/null +++ b/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include "qbackendnodetester.h" +#include "testrenderer.h" + +class tst_GLShaderManager : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void adopt(); + void lookupResource(); + void abandon(); + void insertAfterRemoval(); +}; + +void tst_GLShaderManager::adopt() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + + // THEN + QVERIFY(cache.lookupResource(backendShaderNode1.peerId()) == nullptr); + QVERIFY(cache.lookupResource(backendShaderNode2.peerId()) == nullptr); + QVERIFY(backendShaderNode1.peerId() != backendShaderNode2.peerId()); + + // WHEN + Qt3DRender::Render::GLShader *glShader1 = cache.createOrAdoptExisting(&backendShaderNode1); + + // THEN + QVERIFY(glShader1 != nullptr); + QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); + QCOMPARE(shaderNodeIds.size(), 1); + QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); + + // WHEN + Qt3DRender::Render::GLShader *glShader2 = cache.createOrAdoptExisting(&backendShaderNode2); + + // THEN + QCOMPARE(glShader1, glShader2); + + shaderNodeIds = cache.shaderIdsForProgram(glShader2); + QCOMPARE(shaderNodeIds.size(), 2); + QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); + QCOMPARE(shaderNodeIds.last(), backendShaderNode2.peerId()); +} + +void tst_GLShaderManager::lookupResource() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + + // WHEN + cache.createOrAdoptExisting(&backendShaderNode1); + cache.createOrAdoptExisting(&backendShaderNode2); + + // THEN + Qt3DRender::Render::GLShader *glShader1 = cache.lookupResource(backendShaderNode1.peerId()); + Qt3DRender::Render::GLShader *glShader2 = cache.lookupResource(backendShaderNode2.peerId()); + QVERIFY(glShader1 != nullptr); + QCOMPARE(glShader1, glShader2); + const QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); + QCOMPARE(shaderNodeIds.size(), 2); + QVERIFY(shaderNodeIds.contains(frontendShader1.id())); + QVERIFY(shaderNodeIds.contains(frontendShader2.id())); +} + +void tst_GLShaderManager::abandon() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader1; + Qt3DRender::QShaderProgram frontendShader2; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode1; + Qt3DRender::Render::Shader backendShaderNode2; + + backendShaderNode1.setRenderer(&renderer); + backendShaderNode2.setRenderer(&renderer); + simulateInitialization(&frontendShader1, &backendShaderNode1); + simulateInitialization(&frontendShader2, &backendShaderNode2); + cache.createOrAdoptExisting(&backendShaderNode1); + cache.createOrAdoptExisting(&backendShaderNode2); + + // WHEN + Qt3DRender::Render::GLShader *glShader = cache.lookupResource(backendShaderNode1.peerId()); + cache.abandon(glShader, &backendShaderNode1); + + // THEN + QVector shaderNodeIds = cache.shaderIdsForProgram(glShader); + QVERIFY(cache.takeAbandonned().isEmpty()); + QCOMPARE(shaderNodeIds.size(), 1); + QCOMPARE(shaderNodeIds.first(), backendShaderNode2.peerId()); + + // WHEN + cache.abandon(glShader, &backendShaderNode2); + + // THEN + shaderNodeIds = cache.shaderIdsForProgram(glShader); + QCOMPARE(shaderNodeIds.size(), 0); + const QVector releasedShaders = cache.takeAbandonned(); + QCOMPARE(releasedShaders.size(), 1); + QCOMPARE(releasedShaders.first(), glShader); +} + +void tst_GLShaderManager::insertAfterRemoval() +{ + // GIVEN + Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::QShaderProgram frontendShader; + TestRenderer renderer; + Qt3DRender::Render::Shader backendShaderNode; + + + backendShaderNode.setRenderer(&renderer); + simulateInitialization(&frontendShader, &backendShaderNode); + + // WHEN + Qt3DRender::Render::GLShader *apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); + const Qt3DRender::Render::GLShader *originalApiShader = apiShader1; + + // THEN + auto apiShader2 = cache.lookupResource(frontendShader.id()); + QVERIFY(apiShader1 != nullptr); + QVERIFY(apiShader2 != nullptr); + QVERIFY(apiShader1 == originalApiShader); + QVERIFY(apiShader1 == apiShader2); + + // WHEN + cache.abandon(apiShader1, &backendShaderNode); + + // THEN + Qt3DRender::Render::GLShader *apiShaderEmpty = cache.lookupResource(frontendShader.id()); + QVERIFY(apiShaderEmpty == nullptr); + + // WHEN + apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); + cache.purge(); + apiShader2 = cache.lookupResource(frontendShader.id()); + + // THEN + QVERIFY(apiShader1 != nullptr); + QVERIFY(apiShader2 != nullptr); + QVERIFY(apiShader1 == apiShader2); + QVERIFY(apiShader2 == originalApiShader); +} + +QTEST_APPLESS_MAIN(tst_GLShaderManager) + +#include "tst_glshadermanager.moc" diff --git a/tests/auto/render/opengl/graphicshelpergl2/graphicshelpergl2.pro b/tests/auto/render/opengl/graphicshelpergl2/graphicshelpergl2.pro new file mode 100644 index 000000000..eb8ba7f04 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl2/graphicshelpergl2.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +TARGET = tst_graphicshelpergl2 + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib openglextensions + +CONFIG += testcase + +SOURCES += \ + tst_graphicshelpergl2.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp new file mode 100644 index 000000000..0a43a3040 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp @@ -0,0 +1,1605 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef QT_OPENGL_ES_2 + +#define TEST_SHOULD_BE_PERFORMED 1 + +QT_BEGIN_NAMESPACE + +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +namespace { + +const QByteArray vertCode = QByteArrayLiteral( + "#version 120\n" \ + "attribute vec3 vertexPosition;\n" \ + "attribute vec2 vertexTexCoord;\n" \ + "varying vec2 texCoord;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( + "#version 120\n" \ + "uniform float multiplier;\n" \ + "uniform vec2 multiplierVec2;\n" \ + "uniform vec3 multiplierVec3;\n" \ + "uniform vec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ + " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsInt = QByteArrayLiteral( + "#version 120\n" \ + "uniform int multiplier;\n" \ + "uniform ivec2 multiplierVec2;\n" \ + "uniform ivec3 multiplierVec3;\n" \ + "uniform ivec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ + " gl_FragColor = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( + "#version 120\n" \ + "uniform mat2 m2;\n" \ + "uniform mat2x3 m23;\n" \ + "uniform mat3x2 m32;\n" \ + "uniform mat2x4 m24;\n" \ + "uniform mat4x2 m42;\n" \ + "uniform mat3 m3;\n" \ + "uniform mat3x4 m34;\n" \ + "uniform mat4x3 m43;\n" \ + "uniform mat4 m4;\n" \ + "void main()\n" \ + "{\n" \ + " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ + " gl_FragColor = vec4(1, 0, 0, 1) * lengthSum;\n" \ + "}\n"); + + +const QByteArray fragCodeSamplers = QByteArrayLiteral( + "#version 120\n" \ + "varying vec2 texCoord;\n" \ + "uniform sampler1D s1;\n" \ + "uniform sampler2D s2;\n" \ + "uniform sampler3D s3;\n" \ + "uniform samplerCube scube;\n" \ + "void main()\n" \ + "{\n" \ + " gl_FragColor = vec4(1, 0, 0, 1) *" \ + " texture1D(s1, texCoord.x) *" \ + " texture2D(s2, texCoord) *" \ + " texture3D(s3, vec3(texCoord, 0.0)) *" \ + " textureCube(scube, vec3(texCoord, 0));\n" \ + "}\n"); + +} // anonymous + +class tst_GraphicsHelperGL2 : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void init() + { + m_window.reset(new QWindow); + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + m_window->create(); + + QSurfaceFormat format; + format.setVersion(2, 0); + format.setProfile(QSurfaceFormat::NoProfile); + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + m_window->setFormat(format); + m_glContext.setFormat(format); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to make OpenGL context current"; + return; + } + + if ((m_func = m_glContext.versionFunctions()) != nullptr) { + if (m_glContext.hasExtension(QByteArrayLiteral("GL_ARB_framebuffer_object"))) { + m_fboFuncs = new QOpenGLExtension_ARB_framebuffer_object(); + m_fboFuncs->initializeOpenGLFunctions(); + } + m_glHelper.initializeHelper(&m_glContext, m_func); + m_initializationSuccessful = true; + } + } + + void cleanup() + { + m_glContext.doneCurrent(); + } + + void alphaTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Deprecated + } + + void bindBufferBase() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // Not supported by GL2 + } + + void bindFragDataLocation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void bindFrameBufferAttachment() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureAttachmentId = 0; + m_fboFuncs->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &textureAttachmentId); + QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); + + // Restore state + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + } + + void bindFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundindFBOId = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // Cleanup + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + } + + void bindShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void bindUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void blendEquation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + GLint equation = 0; + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_ADD); + + // WHEN + m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); + + // THEN + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); + } + + void blendFunci() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void blendFuncSeparatei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void boundFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + // WHEN + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + // THEN + GLint boundBuffer = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); + QCOMPARE(GLuint(boundBuffer), fboId); + + // THEN + QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); + + // Reset state + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + } + + void checkFrameBufferComplete() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + QVERIFY(m_glHelper.checkFrameBufferComplete()); + + // Restore + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + } + + void clearBufferf() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void createFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // WHEN + const GLuint fboId = m_glHelper.createFrameBufferObject(); + + // THEN + QVERIFY(fboId != 0); + + // Restore + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + } + + void depthMask() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + GLboolean depthWritingEnabled = false; + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + + // THEN + QVERIFY(depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_FALSE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(!depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_TRUE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(depthWritingEnabled); + } + + void depthTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glDisable(GL_DEPTH_TEST); + m_func->glDepthFunc(GL_LESS); + + // WHEN + m_glHelper.depthTest(GL_LEQUAL); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + GLint depthMode = 0; + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LEQUAL); + + // WHEN + m_glHelper.depthTest(GL_LESS); + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LESS); + } + + void disableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glEnable(GL_CLIP_DISTANCE0 + 5); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + + // WHEN + m_glHelper.disableClipPlane(5); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + } + + void disablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void disablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void drawBuffers() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + QOpenGLTexture *textures[4]; + + // Create 4 attachments + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + // THEN + GLenum status = m_fboFuncs->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // WHEN + GLenum bufferEnum = GL_COLOR_ATTACHMENT4; + m_func->glDrawBuffers(1, &bufferEnum); + + // THEN + GLint enumValue = -1; + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); + + // WHEN + GLint newBufferEnum = 2; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // WHEN + newBufferEnum = 0; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // Restore + m_fboFuncs->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_fboFuncs->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void enableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glDisable(GL_CLIP_DISTANCE0 + 4); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + + // WHEN + m_glHelper.enableClipPlane(4); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + } + + void enablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void enablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void frontFace() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glFrontFace(GL_CW); + + // THEN + GLint face = 0; + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CW); + + // WHEN + m_glHelper.frontFace(GL_CCW); + + // THEN + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CCW); + } + + void getRenderBufferDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void getTextureDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // WHEN + const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + } + + void pointSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // WHEN + m_glHelper.pointSize(false, 0.5f); + // THEN + GLfloat size = 0.0f; + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 0.5f); + } + + void maxClipPlaneCount() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + GLint maxCount = -1; + m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); + + // THEN + QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); + } + + void programUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // Not supported by GL2 + } + + void programAttributesAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeAttributes.size(), 2); + std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); + + const ShaderAttribute attribute1 = activeAttributes.at(0); + QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); + QCOMPARE(attribute1.m_size, 1); + QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); + QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); + + const ShaderAttribute attribute2 = activeAttributes.at(1); + QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); + QCOMPARE(attribute2.m_size, 1); + QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); + QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); + } + + void programUniformsAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniforms.size(), 4); + std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); + + const ShaderUniform uniform1 = activeUniforms.at(0); + QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); + QCOMPARE(uniform1.m_offset, -1); + QCOMPARE(uniform1.m_blockIndex, -1); + QCOMPARE(uniform1.m_arrayStride, -1); + QCOMPARE(uniform1.m_matrixStride, -1); + QCOMPARE(uniform1.m_size, 1); + QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); + QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); + + const ShaderUniform uniform2 = activeUniforms.at(1); + QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); + QCOMPARE(uniform2.m_offset, -1); + QCOMPARE(uniform2.m_blockIndex, -1); + QCOMPARE(uniform2.m_arrayStride, -1); + QCOMPARE(uniform2.m_matrixStride, -1); + QCOMPARE(uniform2.m_size, 1); + QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); + QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); + + const ShaderUniform uniform3 = activeUniforms.at(2); + QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); + QCOMPARE(uniform3.m_offset, -1); + QCOMPARE(uniform3.m_blockIndex, -1); + QCOMPARE(uniform3.m_arrayStride, -1); + QCOMPARE(uniform3.m_matrixStride, -1); + QCOMPARE(uniform3.m_size, 1); + QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); + QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); + + const ShaderUniform uniform4 = activeUniforms.at(3); + QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); + QCOMPARE(uniform4.m_offset, -1); + QCOMPARE(uniform4.m_blockIndex, -1); + QCOMPARE(uniform4.m_arrayStride, -1); + QCOMPARE(uniform4.m_matrixStride, -1); + QCOMPARE(uniform4.m_size, 1); + QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); + QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); + } + + void programShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void releaseFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + if (!m_fboFuncs) + QSKIP("FBO not supported by OpenGL 2.0"); + // GIVEN + GLuint fboId; + m_fboFuncs->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.releaseFrameBufferObject(fboId); + + // THEN + QVERIFY(!m_fboFuncs->glIsFramebuffer(fboId)); + } + + void setMSAAEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glDisable(GL_MULTISAMPLE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + } + + void setAlphaCoverageEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + } + + void setClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // Deprecated in 3.3 core + } + + void setSeamlessCubemap() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported in GL2 + } + + void setVerticesPerPatch() + { + // Not supported in GL2 + } + +#define SUPPORTS_FEATURE(Feature, IsSupported) \ + QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); + + void supportsFeature() + { + SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, (m_fboFuncs != nullptr)); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::Tessellation, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::IndirectDrawing, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::MapBuffer, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::Fences, false); + } + + +#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ + QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; + + void uniformsByteSize_data() + { + QTest::addColumn("fragShader"); + QTest::addColumn("name"); + QTest::addColumn("type"); + QTest::addColumn("componentSize"); + QTest::addColumn("expectedByteSize"); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); + } + + void uniformsByteSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QFETCH(QByteArray, fragShader); + QFETCH(QString, name); + QFETCH(int, type); + QFETCH(int, componentSize); + QFETCH(int, expectedByteSize); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); + QVERIFY(shaderProgram.link()); + + GLint location = shaderProgram.uniformLocation(name); + // WHEN + const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + ShaderUniform matchingUniform; + for (const ShaderUniform &u : activeUniforms) { + if (u.m_location == location) { + matchingUniform = u; + break; + } + } + + // THEN + QCOMPARE(matchingUniform.m_location, location); + QCOMPARE(matchingUniform.m_type, GLuint(type)); + QCOMPARE(matchingUniform.m_size, componentSize); + + // WHEN + const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); + + // THEN + QCOMPARE(expectedByteSize, computedRawByteSize); + + // Restore + m_func->glUseProgram(0); + } + + void useProgram() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + + // THEN + QVERIFY(shaderProgram.link()); + + GLint currentProg = 0; + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + + // WHEN + m_glHelper.useProgram(shaderProgram.programId()); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QCOMPARE(GLuint(currentProg), shaderProgram.programId()); + + // WHEN + m_glHelper.useProgram(0); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + } + + void vertexAttribDivisor() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not available in 3.2 + } + + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void glUniform1fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat value = 883.0f; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1fv(location, 1, &value); + + // THEN + GLfloat setValue = 0.0f; + m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[2] = { 383.0f, 427.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2fv(location, 1, values); + + // THEN + GLfloat setValues[2] = { 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3fv(location, 1, values); + + // THEN + GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint value = 883; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1iv(location, 1, &value); + + // THEN + GLint setValue = 0; + m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[2] = { 383, 427 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2iv(location, 1, values); + + // THEN + GLint setValues[2] = { 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[3] = { 572, 1340, 1584 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3iv(location, 1, values); + + // THEN + GLint setValues[3] = { 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[4] = { 454, 350, 883, 355 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4iv(location, 1, values); + + // THEN + GLint setValues[4] = { 0, 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniform2uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniform3uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniform4uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("m2"); + m_glHelper.glUniformMatrix2fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; + const GLint location = shaderProgram.uniformLocation("m3"); + m_glHelper.glUniformMatrix3fv(location, 1, values); + + // THEN + GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 9; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; + const GLint location = shaderProgram.uniformLocation("m4"); + m_glHelper.glUniformMatrix4fv(location, 1, values); + + // THEN + GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 16; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix3x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix2x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix4x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix3x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void glUniformMatrix4x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void blitFramebuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + +#define ADD_GL_TYPE_ENTRY(Type, Expected) \ + QTest::newRow(#Type) << Type << Expected; + + void uniformTypeFromGLType_data() + { + QTest::addColumn("glType"); + QTest::addColumn("expected"); + + ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); + ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); + ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); + ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); + ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); + } + + void uniformTypeFromGLType() + { + // GIVEN + QFETCH(int, glType); + QFETCH(UniformType, expected); + + // WHEN + UniformType computed = m_glHelper.uniformTypeFromGLType(glType); + + // THEN + QCOMPARE(computed, expected); + } + + void drawBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void readBuffer() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void fenceSync() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void clientWaitSync() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void waitSync() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void wasSyncSignaled() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void deleteSync() + { + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + // Not supported by GL2 + } + + void rasterMode() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 2.0 functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_POLYGON_MODE, &p); + QCOMPARE(p, GL_LINE); + } + +private: + QScopedPointer m_window; + QOpenGLContext m_glContext; + GraphicsHelperGL2 m_glHelper; + QOpenGLFunctions_2_0 *m_func = nullptr; + QOpenGLExtension_ARB_framebuffer_object *m_fboFuncs = nullptr; + bool m_initializationSuccessful = false; +}; + +QT_END_NAMESPACE + +#endif + +int main(int argc, char *argv[]) +{ +#ifdef TEST_SHOULD_BE_PERFORMED + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + tst_GraphicsHelperGL2 tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +#endif + return 0; +} + +#ifdef TEST_SHOULD_BE_PERFORMED +#include "tst_graphicshelpergl2.moc" +#endif diff --git a/tests/auto/render/opengl/graphicshelpergl3_2/graphicshelpergl3_2.pro b/tests/auto/render/opengl/graphicshelpergl3_2/graphicshelpergl3_2.pro new file mode 100644 index 000000000..a613f1279 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl3_2/graphicshelpergl3_2.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +TARGET = tst_graphicshelpergl3_2 + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_graphicshelpergl3_2.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp new file mode 100644 index 000000000..a4a59d7c4 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp @@ -0,0 +1,2294 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) + +#define TEST_SHOULD_BE_PERFORMED 1 + +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +namespace { + +const QByteArray vertCode = QByteArrayLiteral( + "#version 150 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "out vec2 texCoord;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( + "#version 150 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "in int vertexColorIndex;\n" \ + "out vec2 texCoord;\n" \ + "flat out int colorIndex;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " colorIndex = vertexColorIndex;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeFragOutputs = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "out vec2 temp;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ + " temp = vec2(1.0, 0.3);\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "uniform float multiplier;\n" \ + "uniform vec2 multiplierVec2;\n" \ + "uniform vec3 multiplierVec3;\n" \ + "uniform vec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsInt = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "uniform int multiplier;\n" \ + "uniform ivec2 multiplierVec2;\n" \ + "uniform ivec3 multiplierVec3;\n" \ + "uniform ivec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ + " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "uniform uint multiplier;\n" \ + "uniform uvec2 multiplierVec2;\n" \ + "uniform uvec3 multiplierVec3;\n" \ + "uniform uvec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ + " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "uniform mat2 m2;\n" \ + "uniform mat2x3 m23;\n" \ + "uniform mat3x2 m32;\n" \ + "uniform mat2x4 m24;\n" \ + "uniform mat4x2 m42;\n" \ + "uniform mat3 m3;\n" \ + "uniform mat3x4 m34;\n" \ + "uniform mat4x3 m43;\n" \ + "uniform mat4 m4;\n" \ + "void main()\n" \ + "{\n" \ + " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ + " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ + "}\n"); + +const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( + "#version 150 core\n" \ + "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ + "flat in int colorIndex;\n" \ + "uniform ColorArray\n" \ + "{\n" \ + " vec4 colors[256];\n" \ + "};\n" \ + "void main()\n" \ + "{\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeSamplers = QByteArrayLiteral( + "#version 150 core\n" \ + "in vec2 texCoord;\n" \ + "out vec4 color;\n" \ + "uniform sampler1D s1;\n" \ + "uniform sampler2D s2;\n" \ + "uniform sampler2DArray s2a;\n" \ + "uniform sampler3D s3;\n" \ + "uniform samplerCube scube;\n" \ + "uniform sampler2DRect srect;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1, 0, 0, 1) *" \ + " texture(s1, texCoord.x) *" \ + " texture(s2, texCoord) *" \ + " texture(s2a, vec3(texCoord, 0.0)) *" \ + " texture(s3, vec3(texCoord, 0.0)) *" \ + " texture(scube, vec3(texCoord, 0)) *" \ + " texture(srect, texCoord);\n" \ + "}\n"); + +} // anonymous + +class tst_GraphicsHelperGL3_2 : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void init() + { + m_window.reset(new QWindow); + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + m_window->create(); + + QSurfaceFormat format; + format.setVersion(3, 2); + format.setProfile(QSurfaceFormat::CoreProfile); + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + m_window->setFormat(format); + m_glContext.setFormat(format); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to make OpenGL context current"; + return; + } + + if ((m_func = m_glContext.versionFunctions()) != nullptr) { + m_glHelper.initializeHelper(&m_glContext, m_func); + m_initializationSuccessful = true; + } + } + + void cleanup() + { + m_glContext.doneCurrent(); + } + + void alphaTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + // Deprecated + } + + void bindBufferBase() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint bufferId = 0; + // WHEN + m_func->glGenBuffers(1, &bufferId); + // THEN + QVERIFY(bufferId != 0); + + + // WHEN + m_func->glBindBuffer(GL_UNIFORM_BUFFER, bufferId); + m_glHelper.bindBufferBase(GL_UNIFORM_BUFFER, 2, bufferId); + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundToPointBufferId = 0; + m_func->glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, 2, &boundToPointBufferId); + QVERIFY(boundToPointBufferId == GLint(bufferId)); + + // Restore to sane state + m_func->glBindBuffer(GL_UNIFORM_BUFFER, 0); + m_func->glDeleteBuffers(1, &bufferId); + } + + void bindFragDataLocation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // WHEN + QHash fragLocations; + fragLocations.insert(QStringLiteral("temp"), 2); + fragLocations.insert(QStringLiteral("color"), 1); + m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); + + // THEN + QVERIFY(shaderProgram.link()); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); + const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); + QCOMPARE(tempLocation, 2); + QCOMPARE(colorLocation, 1); + } + + void bindFrameBufferAttachment() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureAttachmentId = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &textureAttachmentId); + QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void bindFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundindFBOId = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // Cleanup + m_func->glDeleteFramebuffers(1, &fboId); + } + + void bindShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + // Not supported in OpenGL 3.2 + } + + void bindUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void blendEquation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLint equation = 0; + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_ADD); + + // WHEN + m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); + + // THEN + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); + } + + void blendFunci() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + // Not supported by OpenGL 3.2 + } + + void blendFuncSeparatei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // Not supported by OpenGL 3.2 + } + + void boundFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + // THEN + GLint boundBuffer = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); + QCOMPARE(GLuint(boundBuffer), fboId); + + // THEN + QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); + + // Reset state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void checkFrameBufferComplete() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + QVERIFY(m_glHelper.checkFrameBufferComplete()); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void clearBufferf() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + // Create 4 attachments + QOpenGLTexture *textures[4]; + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // Set Draw buffers + GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; + m_func->glDrawBuffers(1, &clearBufferEnum); + + const GLint bufferIndex = 0; // index of the element in the draw buffers + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // WHEN + const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); + m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); + error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + QVector colors(512 * 512); + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + for (const QVector4D c : colors) { + QVERIFY(c == clearValue1); + } + + // WHEN + const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); + m_glHelper.clearBufferf(bufferIndex, clearValue2); + + // THEN + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + for (const QVector4D c : colors) { + QVERIFY(c == clearValue2); + } + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void createFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // WHEN + const GLuint fboId = m_glHelper.createFrameBufferObject(); + + // THEN + QVERIFY(fboId != 0); + + // Restore + m_func->glDeleteFramebuffers(1, &fboId); + } + + void depthMask() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLboolean depthWritingEnabled = false; + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + + // THEN + QVERIFY(depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_FALSE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(!depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_TRUE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(depthWritingEnabled); + } + + void depthTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_DEPTH_TEST); + m_func->glDepthFunc(GL_LESS); + + // WHEN + m_glHelper.depthTest(GL_LEQUAL); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + GLint depthMode = 0; + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LEQUAL); + + // WHEN + m_glHelper.depthTest(GL_LESS); + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LESS); + } + + void disableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_CLIP_DISTANCE0 + 5); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + + // WHEN + m_glHelper.disableClipPlane(5); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + } + + void disablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glEnablei(GL_BLEND, 2); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); + + // WHEN + m_glHelper.disablei(GL_BLEND, 2); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); + } + + void disablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.disablePrimitiveRestart(); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + } + + void drawBuffers() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + QOpenGLTexture *textures[4]; + + // Create 4 attachments + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // WHEN + GLenum bufferEnum = GL_COLOR_ATTACHMENT4; + m_func->glDrawBuffers(1, &bufferEnum); + + // THEN + GLint enumValue = -1; + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); + + // WHEN + GLint newBufferEnum = 2; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // WHEN + newBufferEnum = 0; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void enableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_CLIP_DISTANCE0 + 4); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + + // WHEN + m_glHelper.enableClipPlane(4); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + } + + void enablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisablei(GL_BLEND, 4); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); + + // WHEN + m_glHelper.enablei(GL_BLEND, 4); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); + } + + void enablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.enablePrimitiveRestart(883); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + GLint restartIndex = 0; + m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); + QCOMPARE(restartIndex, 883); + + // Restore + m_func->glDisable(GL_PRIMITIVE_RESTART); + } + + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void frontFace() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glFrontFace(GL_CW); + + // THEN + GLint face = 0; + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CW); + + // WHEN + m_glHelper.frontFace(GL_CCW); + + // THEN + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CCW); + } + + void getRenderBufferDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint renderBufferId = 0; + m_func->glGenRenderbuffers(1, &renderBufferId); + QVERIFY(renderBufferId != 0); + + // WHEN + m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); + m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); + m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); + const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + + // Restore + m_func->glDeleteRenderbuffers(1, &renderBufferId); + } + + void getTextureDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // WHEN + const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + } + + void pointSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PROGRAM_POINT_SIZE); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + GLfloat size = 0; + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 1.0f); + + // WHEN + m_glHelper.pointSize(false, 0.5f); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 0.5f); + } + + void maxClipPlaneCount() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLint maxCount = -1; + m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); + + // THEN + QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); + } + + void programUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniformBlocks.size(), 1); + const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); + + QCOMPARE(uniformBlock.m_activeUniformsCount, 1); + QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); + + GLint blockIndex = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + GLint blockBinding = -1; + m_func->glGetActiveUniformBlockiv(shaderProgram.programId(), blockIndex, GL_UNIFORM_BLOCK_BINDING, &blockBinding); + QCOMPARE(blockIndex, uniformBlock.m_index); + QCOMPARE(blockBinding, uniformBlock.m_binding); + } + + void programAttributesAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeAttributes.size(), 2); + std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); + + const ShaderAttribute attribute1 = activeAttributes.at(0); + QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); + QCOMPARE(attribute1.m_size, 1); + QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); + QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); + + const ShaderAttribute attribute2 = activeAttributes.at(1); + QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); + QCOMPARE(attribute2.m_size, 1); + QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); + QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); + } + + void programUniformsAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniforms.size(), 4); + std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); + + const ShaderUniform uniform1 = activeUniforms.at(0); + QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); + QCOMPARE(uniform1.m_offset, -1); + QCOMPARE(uniform1.m_blockIndex, -1); + QCOMPARE(uniform1.m_arrayStride, -1); + QCOMPARE(uniform1.m_matrixStride, -1); + QCOMPARE(uniform1.m_size, 1); + QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); + QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); + + const ShaderUniform uniform2 = activeUniforms.at(1); + QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); + QCOMPARE(uniform2.m_offset, -1); + QCOMPARE(uniform2.m_blockIndex, -1); + QCOMPARE(uniform2.m_arrayStride, -1); + QCOMPARE(uniform2.m_matrixStride, -1); + QCOMPARE(uniform2.m_size, 1); + QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); + QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); + + const ShaderUniform uniform3 = activeUniforms.at(2); + QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); + QCOMPARE(uniform3.m_offset, -1); + QCOMPARE(uniform3.m_blockIndex, -1); + QCOMPARE(uniform3.m_arrayStride, -1); + QCOMPARE(uniform3.m_matrixStride, -1); + QCOMPARE(uniform3.m_size, 1); + QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); + QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); + + const ShaderUniform uniform4 = activeUniforms.at(3); + QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); + QCOMPARE(uniform4.m_offset, -1); + QCOMPARE(uniform4.m_blockIndex, -1); + QCOMPARE(uniform4.m_arrayStride, -1); + QCOMPARE(uniform4.m_matrixStride, -1); + QCOMPARE(uniform4.m_size, 1); + QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); + QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); + } + + void programShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // Not supported in 3.2 + } + + void releaseFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.releaseFrameBufferObject(fboId); + + // THEN + QVERIFY(!m_func->glIsFramebuffer(fboId)); + } + + void setMSAAEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_MULTISAMPLE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + } + + void setAlphaCoverageEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + } + + void setClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // Deprecated in 3.3 core + } + + void setSeamlessCubemap() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + + void setVerticesPerPatch() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + +#define SUPPORTS_FEATURE(Feature, IsSupported) \ + QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); + + void supportsFeature() + { + SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); + // Tesselation could be true or false depending on extensions so not tested + SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, true); + } + + +#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ + QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; + + void uniformsByteSize_data() + { + QTest::addColumn("fragShader"); + QTest::addColumn("name"); + QTest::addColumn("type"); + QTest::addColumn("componentSize"); + QTest::addColumn("expectedByteSize"); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplier", GL_UNSIGNED_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec2", GL_UNSIGNED_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec3", GL_UNSIGNED_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec4", GL_UNSIGNED_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2a", GL_SAMPLER_2D_ARRAY, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "srect", GL_SAMPLER_2D_RECT, 1, 4); + } + + void uniformsByteSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QFETCH(QByteArray, fragShader); + QFETCH(QString, name); + QFETCH(int, type); + QFETCH(int, componentSize); + QFETCH(int, expectedByteSize); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); + QVERIFY(shaderProgram.link()); + + GLint location = shaderProgram.uniformLocation(name); + // WHEN + const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + ShaderUniform matchingUniform; + for (const ShaderUniform &u : activeUniforms) { + if (u.m_location == location) { + matchingUniform = u; + break; + } + } + + + // THEN + QCOMPARE(matchingUniform.m_location, location); + QCOMPARE(matchingUniform.m_type, GLuint(type)); + QCOMPARE(matchingUniform.m_size, componentSize); + + // WHEN + const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); + + // THEN + QCOMPARE(expectedByteSize, computedRawByteSize); + + // Restore + m_func->glUseProgram(0); + } + + void useProgram() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // THEN + QVERIFY(shaderProgram.link()); + + GLint currentProg = 0; + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + + // WHEN + m_glHelper.useProgram(shaderProgram.programId()); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QCOMPARE(GLuint(currentProg), shaderProgram.programId()); + + // WHEN + m_glHelper.useProgram(0); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + } + + void vertexAttribDivisor() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + // Not available in 3.2 + } + + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void glUniform1fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat value = 883.0f; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1fv(location, 1, &value); + + // THEN + GLfloat setValue = 0.0f; + m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[2] = { 383.0f, 427.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2fv(location, 1, values); + + // THEN + GLfloat setValues[2] = { 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3fv(location, 1, values); + + // THEN + GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint value = 883; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1iv(location, 1, &value); + + // THEN + GLint setValue = 0; + m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[2] = { 383, 427 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2iv(location, 1, values); + + // THEN + GLint setValues[2] = { 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[3] = { 572, 1340, 1584 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3iv(location, 1, values); + + // THEN + GLint setValues[3] = { 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[4] = { 454, 350, 883, 355 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4iv(location, 1, values); + + // THEN + GLint setValues[4] = { 0, 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint value = 883U; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1uiv(location, 1, &value); + + // THEN + GLuint setValue = 0U; + m_func->glGetUniformuiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[2] = { 383U, 427U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2uiv(location, 1, values); + + // THEN + GLuint setValues[2] = { 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[3] = { 572U, 1340U, 1584U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3uiv(location, 1, values); + + // THEN + GLuint setValues[3] = { 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[4] = { 454U, 350U, 883U, 355U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4uiv(location, 1, values); + + // THEN + GLuint setValues[4] = { 0U, 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("m2"); + m_glHelper.glUniformMatrix2fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; + const GLint location = shaderProgram.uniformLocation("m3"); + m_glHelper.glUniformMatrix3fv(location, 1, values); + + // THEN + GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 9; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; + const GLint location = shaderProgram.uniformLocation("m4"); + m_glHelper.glUniformMatrix4fv(location, 1, values); + + // THEN + GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 16; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m23"); + m_glHelper.glUniformMatrix2x3fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m32"); + m_glHelper.glUniformMatrix3x2fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m24"); + m_glHelper.glUniformMatrix2x4fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m42"); + m_glHelper.glUniformMatrix4x2fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f}; + const GLint location = shaderProgram.uniformLocation("m34"); + m_glHelper.glUniformMatrix3x4fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m43"); + m_glHelper.glUniformMatrix4x3fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void blitFramebuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + GLint maxSamples; + m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples < 1) + QSKIP("This test requires an implementation that supports multisampled textures"); + + // GIVEN + GLuint fbos[2]; + GLuint fboTextures[2]; + + m_func->glGenFramebuffers(2, fbos); + m_func->glGenTextures(2, fboTextures); + + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + + m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); + m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + m_func->glBindTexture(GL_TEXTURE_2D, 0); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); + + GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); + + status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + m_func->glEnable(GL_MULTISAMPLE); + m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); + m_func->glClear(GL_COLOR_BUFFER_BIT); + m_func->glDisable(GL_MULTISAMPLE); + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); + + // WHEN + m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + + GLuint result[10*10]; + m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); + + // THEN + GLuint v = (0.2f) * 255; + v = v | (v<<8) | (v<<16) | (v<<24); + for (GLuint value : result) { + QCOMPARE(value, v); + } + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + m_func->glDeleteFramebuffers(2, fbos); + m_func->glDeleteTextures(2, fboTextures); + } + +#define ADD_GL_TYPE_ENTRY(Type, Expected) \ + QTest::newRow(#Type) << Type << Expected; + + void uniformTypeFromGLType_data() + { + QTest::addColumn("glType"); + QTest::addColumn("expected"); + + ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); + ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); + ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); + ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); + ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); + } + + void uniformTypeFromGLType() + { + // GIVEN + QFETCH(int, glType); + QFETCH(UniformType, expected); + + // WHEN + UniformType computed = m_glHelper.uniformTypeFromGLType(glType); + + // THEN + QCOMPARE(computed, expected); + } + + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void fenceSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + // THEN + QVERIFY(sync != nullptr); + QCOMPARE(m_func->glIsSync(sync), GL_TRUE); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void clientWaitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + QElapsedTimer t; + t.start(); + + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + m_glHelper.clientWaitSync(sync, 1000000); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + qDebug() << t.nsecsElapsed(); + } + + void waitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void wasSyncSignaled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // Shouldn't loop forever + while (!m_glHelper.wasSyncSignaled(sync)) + ; + } + + void deleteSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_glHelper.clientWaitSync(sync, GLuint64(-1)); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); + + // WHEN + m_glHelper.deleteSync(sync); + + // THEN + QCOMPARE(m_func->glIsSync(sync), GL_FALSE); + } + + void rasterMode() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.2 functions not supported"); + + m_func->glGetError(); + + m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_POLYGON_MODE, &p); + QCOMPARE(p, GL_LINE); + } + +private: + QScopedPointer m_window; + QOpenGLContext m_glContext; + GraphicsHelperGL3_2 m_glHelper; + QOpenGLFunctions_3_2_Core *m_func = nullptr; + bool m_initializationSuccessful = false; +}; + +#endif + +int main(int argc, char *argv[]) +{ +#ifdef TEST_SHOULD_BE_PERFORMED + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + tst_GraphicsHelperGL3_2 tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +#endif + return 0; +} + +#ifdef TEST_SHOULD_BE_PERFORMED +#include "tst_graphicshelpergl3_2.moc" +#endif diff --git a/tests/auto/render/opengl/graphicshelpergl3_3/graphicshelpergl3_3.pro b/tests/auto/render/opengl/graphicshelpergl3_3/graphicshelpergl3_3.pro new file mode 100644 index 000000000..5ef0b6806 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl3_3/graphicshelpergl3_3.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +TARGET = tst_graphicshelpergl3_3 + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_graphicshelpergl3_3.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp new file mode 100644 index 000000000..3e4a052ba --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -0,0 +1,2393 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_3_2) + +#define TEST_SHOULD_BE_PERFORMED 1 + +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +namespace { + +const QByteArray vertCode = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "out vec2 texCoord;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec3 vertexPosition;\n" \ + "in vec2 vertexTexCoord;\n" \ + "in int vertexColorIndex;\n" \ + "out vec2 texCoord;\n" \ + "flat out int colorIndex;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " colorIndex = vertexColorIndex;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeFragOutputs = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "out vec2 temp;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ + " temp = vec2(1.0, 0.3);\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "uniform float multiplier;\n" \ + "uniform vec2 multiplierVec2;\n" \ + "uniform vec3 multiplierVec3;\n" \ + "uniform vec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsInt = QByteArrayLiteral( + "#version 330 core\n" \ + "out ivec4 color;\n" \ + "uniform int multiplier;\n" \ + "uniform ivec2 multiplierVec2;\n" \ + "uniform ivec3 multiplierVec3;\n" \ + "uniform ivec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ + " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( + "#version 330 core\n" \ + "out uvec4 color;\n" \ + "uniform uint multiplier;\n" \ + "uniform uvec2 multiplierVec2;\n" \ + "uniform uvec3 multiplierVec3;\n" \ + "uniform uvec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ + " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "uniform mat2 m2;\n" \ + "uniform mat2x3 m23;\n" \ + "uniform mat3x2 m32;\n" \ + "uniform mat2x4 m24;\n" \ + "uniform mat4x2 m42;\n" \ + "uniform mat3 m3;\n" \ + "uniform mat3x4 m34;\n" \ + "uniform mat4x3 m43;\n" \ + "uniform mat4 m4;\n" \ + "void main()\n" \ + "{\n" \ + " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ + " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ + "}\n"); + +const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( + "#version 330 core\n" \ + "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ + "flat in int colorIndex;\n" \ + "uniform ColorArray\n" \ + "{\n" \ + " vec4 colors[256];\n" \ + "};\n" \ + "void main()\n" \ + "{\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeSamplers = QByteArrayLiteral( + "#version 330 core\n" \ + "in vec2 texCoord;\n" \ + "out vec4 color;\n" \ + "uniform sampler1D s1;\n" \ + "uniform sampler2D s2;\n" \ + "uniform sampler2DArray s2a;\n" \ + "uniform sampler3D s3;\n" \ + "uniform samplerCube scube;\n" \ + "uniform sampler2DRect srect;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1, 0, 0, 1) *" \ + " texture(s1, texCoord.x) *" \ + " texture(s2, texCoord) *" \ + " texture(s2a, vec3(texCoord, 0.0)) *" \ + " texture(s3, vec3(texCoord, 0.0)) *" \ + " texture(scube, vec3(texCoord, 0)) *" \ + " texture(srect, texCoord);\n" \ + "}\n"); + +} // anonymous + +class tst_GraphicsHelperGL3_3 : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void init() + { + m_window.reset(new QWindow); + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + + QSurfaceFormat format; + format.setVersion(3, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + m_window->setFormat(format); + m_glContext.setFormat(format); + + m_window->create(); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to maed OpenGL context current"; + return; + } + + if ((m_func = m_glContext.versionFunctions()) != nullptr) { + m_glHelper.initializeHelper(&m_glContext, m_func); + m_initializationSuccessful = true; + } + } + + void cleanup() + { + m_glContext.doneCurrent(); + } + + void alphaTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Deprecated + } + + void bindBufferBase() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint bufferId = 0; + // WHEN + m_func->glGenBuffers(1, &bufferId); + // THEN + QVERIFY(bufferId != 0); + + + // WHEN + m_func->glBindBuffer(GL_UNIFORM_BUFFER, bufferId); + m_glHelper.bindBufferBase(GL_UNIFORM_BUFFER, 2, bufferId); + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundToPointBufferId = 0; + m_func->glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, 2, &boundToPointBufferId); + QVERIFY(boundToPointBufferId == GLint(bufferId)); + + // Restore to sane state + m_func->glBindBuffer(GL_UNIFORM_BUFFER, 0); + m_func->glDeleteBuffers(1, &bufferId); + } + + void bindFragDataLocation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // WHEN + QHash fragLocations; + fragLocations.insert(QStringLiteral("temp"), 2); + fragLocations.insert(QStringLiteral("color"), 1); + m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); + + // THEN + QVERIFY(shaderProgram.link()); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); + const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); + QCOMPARE(tempLocation, 2); + QCOMPARE(colorLocation, 1); + } + + void bindFrameBufferAttachment() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + { + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + GLint maxAttachmentsCount = 0; + m_func->glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachmentsCount); + + // THEN + QVERIFY(fboId != 0); + QVERIFY(maxAttachmentsCount >= 3); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QCOMPARE(int(status), GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureAttachmentId = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &textureAttachmentId); + QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + { // Check All Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_TRUE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { // Check Specific Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureFace = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + &textureFace); + QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_FALSE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + } + } + + void bindFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundindFBOId = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // Cleanup + m_func->glDeleteFramebuffers(1, &fboId); + } + + void bindShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Not supported in OpenGL 3.3 + } + + void bindUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void blendEquation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLint equation = 0; + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_ADD); + + // WHEN + m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); + + // THEN + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); + } + + void blendFunci() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // Not supported by OpenGL 3.3 + } + + void blendFuncSeparatei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Not supported by OpenGL 3.3 + } + + void boundFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + // THEN + GLint boundBuffer = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); + QCOMPARE(GLuint(boundBuffer), fboId); + + // THEN + QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); + + // Reset state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void checkFrameBufferComplete() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + QVERIFY(m_glHelper.checkFrameBufferComplete()); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void clearBufferf() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + // Create 4 attachments + QOpenGLTexture *textures[4]; + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // Set Draw buffers + GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; + m_func->glDrawBuffers(1, &clearBufferEnum); + + const GLint bufferIndex = 0; // index of the element in the draw buffers + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // WHEN + const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); + m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); + error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + QVector colors(512 * 512); + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + + for (const QVector4D c : colors) { + QVERIFY(c == clearValue1); + } + + // WHEN + const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); + m_glHelper.clearBufferf(bufferIndex, clearValue2); + + // THEN + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + for (const QVector4D c : colors) { + QVERIFY(c == clearValue2); + } + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void createFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // WHEN + const GLuint fboId = m_glHelper.createFrameBufferObject(); + + // THEN + QVERIFY(fboId != 0); + + // Restore + m_func->glDeleteFramebuffers(1, &fboId); + } + + void depthMask() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLboolean depthWritingEnabled = false; + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + + // THEN + QVERIFY(depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_FALSE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(!depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_TRUE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(depthWritingEnabled); + } + + void depthTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_DEPTH_TEST); + m_func->glDepthFunc(GL_LESS); + + // WHEN + m_glHelper.depthTest(GL_LEQUAL); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + GLint depthMode = 0; + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LEQUAL); + + // WHEN + m_glHelper.depthTest(GL_LESS); + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LESS); + } + + void disableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_CLIP_DISTANCE0 + 5); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + + // WHEN + m_glHelper.disableClipPlane(5); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + } + + void disablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnablei(GL_BLEND, 2); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); + + // WHEN + m_glHelper.disablei(GL_BLEND, 2); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); + } + + void disablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.disablePrimitiveRestart(); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + } + + void drawBuffers() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + QOpenGLTexture *textures[4]; + + // Create 4 attachments + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // WHEN + GLenum bufferEnum = GL_COLOR_ATTACHMENT4; + m_func->glDrawBuffers(1, &bufferEnum); + + // THEN + GLint enumValue = -1; + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); + + // WHEN + GLint newBufferEnum = 2; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // WHEN + newBufferEnum = 0; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void enableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_CLIP_DISTANCE0 + 4); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + + // WHEN + m_glHelper.enableClipPlane(4); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + } + + void enablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisablei(GL_BLEND, 4); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); + + // WHEN + m_glHelper.enablei(GL_BLEND, 4); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); + } + + void enablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.enablePrimitiveRestart(883); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + GLint restartIndex = 0; + m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); + QCOMPARE(restartIndex, 883); + + // Restore + m_func->glDisable(GL_PRIMITIVE_RESTART); + } + + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void frontFace() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glFrontFace(GL_CW); + + // THEN + GLint face = 0; + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CW); + + // WHEN + m_glHelper.frontFace(GL_CCW); + + // THEN + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CCW); + } + + void getRenderBufferDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint renderBufferId = 0; + m_func->glGenRenderbuffers(1, &renderBufferId); + QVERIFY(renderBufferId != 0); + + // WHEN + m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); + m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); + m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); + const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + + // Restore + m_func->glDeleteRenderbuffers(1, &renderBufferId); + } + + void getTextureDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // WHEN + const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + } + + void pointSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PROGRAM_POINT_SIZE); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + GLfloat size = 0; + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 1.0f); + + // WHEN + m_glHelper.pointSize(false, 0.5f); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 0.5f); + } + + void maxClipPlaneCount() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLint maxCount = -1; + m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); + + // THEN + QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); + } + + void programUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniformBlocks.size(), 1); + const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); + + QCOMPARE(uniformBlock.m_activeUniformsCount, 1); + QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); + + GLint blockIndex = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + GLint blockBinding = -1; + m_func->glGetActiveUniformBlockiv(shaderProgram.programId(), blockIndex, GL_UNIFORM_BLOCK_BINDING, &blockBinding); + QCOMPARE(blockIndex, uniformBlock.m_index); + QCOMPARE(blockBinding, uniformBlock.m_binding); + } + + void programAttributesAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeAttributes.size(), 2); + std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_name < b.m_name; }); + + const ShaderAttribute attribute1 = activeAttributes.at(0); + QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); + QCOMPARE(attribute1.m_size, 1); + QCOMPARE(attribute1.m_location, shaderProgram.attributeLocation("vertexPosition")); + QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); + + const ShaderAttribute attribute2 = activeAttributes.at(1); + QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); + QCOMPARE(attribute2.m_size, 1); + QCOMPARE(attribute2.m_location, shaderProgram.attributeLocation("vertexTexCoord")); + QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); + } + + void programUniformsAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniforms.size(), 4); + std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_name < b.m_name; }); + + const ShaderUniform uniform1 = activeUniforms.at(0); + QCOMPARE(uniform1.m_location, shaderProgram.uniformLocation("multiplier")); + QCOMPARE(uniform1.m_offset, -1); + QCOMPARE(uniform1.m_blockIndex, -1); + QCOMPARE(uniform1.m_arrayStride, -1); + QCOMPARE(uniform1.m_matrixStride, -1); + QCOMPARE(uniform1.m_size, 1); + QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); + QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); + + const ShaderUniform uniform2 = activeUniforms.at(1); + QCOMPARE(uniform2.m_location, shaderProgram.uniformLocation("multiplierVec2")); + QCOMPARE(uniform2.m_offset, -1); + QCOMPARE(uniform2.m_blockIndex, -1); + QCOMPARE(uniform2.m_arrayStride, -1); + QCOMPARE(uniform2.m_matrixStride, -1); + QCOMPARE(uniform2.m_size, 1); + QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); + QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); + + const ShaderUniform uniform3 = activeUniforms.at(2); + QCOMPARE(uniform3.m_location, shaderProgram.uniformLocation("multiplierVec3")); + QCOMPARE(uniform3.m_offset, -1); + QCOMPARE(uniform3.m_blockIndex, -1); + QCOMPARE(uniform3.m_arrayStride, -1); + QCOMPARE(uniform3.m_matrixStride, -1); + QCOMPARE(uniform3.m_size, 1); + QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); + QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); + + const ShaderUniform uniform4 = activeUniforms.at(3); + QCOMPARE(uniform4.m_location, shaderProgram.uniformLocation("multiplierVec4")); + QCOMPARE(uniform4.m_offset, -1); + QCOMPARE(uniform4.m_blockIndex, -1); + QCOMPARE(uniform4.m_arrayStride, -1); + QCOMPARE(uniform4.m_matrixStride, -1); + QCOMPARE(uniform4.m_size, 1); + QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); + QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); + } + + void programShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Not supported in 3.3 + } + + void releaseFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.releaseFrameBufferObject(fboId); + + // THEN + QVERIFY(!m_func->glIsFramebuffer(fboId)); + } + + void setMSAAEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_MULTISAMPLE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + } + + void setAlphaCoverageEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + } + + void setClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // Deprecated in 3.3 core + } + + void setSeamlessCubemap() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + + void setVerticesPerPatch() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + +#define SUPPORTS_FEATURE(Feature, IsSupported) \ + QVERIFY(m_glHelper.supportsFeature(Feature) == IsSupported); + + void supportsFeature() + { + SUPPORTS_FEATURE(GraphicsHelperInterface::MRT, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::BindableFragmentOutputs, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::PrimitiveRestart, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::RenderBufferDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::TextureDimensionRetrieval, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::UniformBufferObject, true); + SUPPORTS_FEATURE(GraphicsHelperInterface::ShaderStorageObject, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::Compute, false); + SUPPORTS_FEATURE(GraphicsHelperInterface::DrawBuffersBlend, false); + // Tesselation could be true or false depending on extensions so not tested + SUPPORTS_FEATURE(GraphicsHelperInterface::BlitFramebuffer, true); + } + + +#define ADD_UNIFORM_ENTRY(FragShader, Name, Type, ComponentSize, ExpectedRawSize) \ + QTest::newRow(#FragShader"_"#Type) << FragShader << QStringLiteral(Name) << Type << ComponentSize << ExpectedRawSize; + + void uniformsByteSize_data() + { + QTest::addColumn("fragShader"); + QTest::addColumn("name"); + QTest::addColumn("type"); + QTest::addColumn("componentSize"); + QTest::addColumn("expectedByteSize"); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplier", GL_FLOAT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec2", GL_FLOAT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec3",GL_FLOAT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, "multiplierVec4", GL_FLOAT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplier", GL_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec2", GL_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec3", GL_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, "multiplierVec4", GL_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplier", GL_UNSIGNED_INT, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec2", GL_UNSIGNED_INT_VEC2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec3", GL_UNSIGNED_INT_VEC3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, "multiplierVec4", GL_UNSIGNED_INT_VEC4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m2", GL_FLOAT_MAT2, 1, 4 * 2 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m23", GL_FLOAT_MAT2x3, 1, 4 * 2 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m32", GL_FLOAT_MAT3x2, 1, 4 * 3 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m24", GL_FLOAT_MAT2x4, 1, 4 * 2 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m42", GL_FLOAT_MAT4x2, 1, 4 * 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m3", GL_FLOAT_MAT3, 1, 4 * 3 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m34", GL_FLOAT_MAT3x4, 1, 4 * 3 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m43", GL_FLOAT_MAT4x3, 1, 4 * 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, "m4", GL_FLOAT_MAT4, 1, 4 * 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s1", GL_SAMPLER_1D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2", GL_SAMPLER_2D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s2a", GL_SAMPLER_2D_ARRAY, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "s3", GL_SAMPLER_3D, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "scube", GL_SAMPLER_CUBE, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, "srect", GL_SAMPLER_2D_RECT, 1, 4); + } + + void uniformsByteSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QFETCH(QByteArray, fragShader); + QFETCH(QString, name); + QFETCH(int, type); + QFETCH(int, componentSize); + QFETCH(int, expectedByteSize); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); + QVERIFY(shaderProgram.link()); + + GLint location = shaderProgram.uniformLocation(name); + // WHEN + const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + ShaderUniform matchingUniform; + for (const ShaderUniform &u : activeUniforms) { + if (u.m_location == location) { + matchingUniform = u; + break; + } + } + + + // THEN + QCOMPARE(matchingUniform.m_location, location); + QCOMPARE(matchingUniform.m_type, GLuint(type)); + QCOMPARE(matchingUniform.m_size, componentSize); + + // WHEN + const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); + + // THEN + QCOMPARE(expectedByteSize, computedRawByteSize); + + // Restore + m_func->glUseProgram(0); + } + + + void useProgram() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // THEN + QVERIFY(shaderProgram.link()); + + GLint currentProg = 0; + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + + // WHEN + m_glHelper.useProgram(shaderProgram.programId()); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QCOMPARE(GLuint(currentProg), shaderProgram.programId()); + + // WHEN + m_glHelper.useProgram(0); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + } + + void vertexAttribDivisor() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + } + + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void glUniform1fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat value = 883.0f; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1fv(location, 1, &value); + + // THEN + GLfloat setValue = 0.0f; + m_func->glGetUniformfv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[2] = { 383.0f, 427.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2fv(location, 1, values); + + // THEN + GLfloat setValues[2] = { 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3fv(location, 1, values); + + // THEN + GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint value = 883; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1iv(location, 1, &value); + + // THEN + GLint setValue = 0; + m_func->glGetUniformiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[2] = { 383, 427 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2iv(location, 1, values); + + // THEN + GLint setValues[2] = { 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[3] = { 572, 1340, 1584 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3iv(location, 1, values); + + // THEN + GLint setValues[3] = { 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[4] = { 454, 350, 883, 355 }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4iv(location, 1, values); + + // THEN + GLint setValues[4] = { 0, 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint value = 883U; + const GLint location = shaderProgram.uniformLocation("multiplier"); + m_glHelper.glUniform1uiv(location, 1, &value); + + // THEN + GLuint setValue = 0U; + m_func->glGetUniformuiv(shaderProgram.programId(), location, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[2] = { 383U, 427U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec2"); + m_glHelper.glUniform2uiv(location, 1, values); + + // THEN + GLuint setValues[2] = { 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[3] = { 572U, 1340U, 1584U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec3"); + m_glHelper.glUniform3uiv(location, 1, values); + + // THEN + GLuint setValues[3] = { 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[4] = { 454U, 350U, 883U, 355U }; + const GLint location = shaderProgram.uniformLocation("multiplierVec4"); + m_glHelper.glUniform4uiv(location, 1, values); + + // THEN + GLuint setValues[4] = { 0U, 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + const GLint location = shaderProgram.uniformLocation("m2"); + m_glHelper.glUniformMatrix2fv(location, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; + const GLint location = shaderProgram.uniformLocation("m3"); + m_glHelper.glUniformMatrix3fv(location, 1, values); + + // THEN + GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 9; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; + const GLint location = shaderProgram.uniformLocation("m4"); + m_glHelper.glUniformMatrix4fv(location, 1, values); + + // THEN + GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 16; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m23"); + m_glHelper.glUniformMatrix2x3fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m32"); + m_glHelper.glUniformMatrix3x2fv(location, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m24"); + m_glHelper.glUniformMatrix2x4fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m42"); + m_glHelper.glUniformMatrix4x2fv(location, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f}; + const GLint location = shaderProgram.uniformLocation("m34"); + m_glHelper.glUniformMatrix3x4fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + const GLint location = shaderProgram.uniformLocation("m43"); + m_glHelper.glUniformMatrix4x3fv(location, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), location, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + + void blitFramebuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + GLint maxSamples; + m_func->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (maxSamples < 1) + QSKIP("This test requires an implementation that supports multisampled textures"); + + // GIVEN + GLuint fbos[2]; + GLuint fboTextures[2]; + + m_func->glGenFramebuffers(2, fbos); + m_func->glGenTextures(2, fboTextures); + + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, maxSamples, GL_RGBA8, 10, 10, true); + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + + m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); + m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + m_func->glBindTexture(GL_TEXTURE_2D, 0); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); + + GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); + + status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QCOMPARE(status, GLenum(GL_FRAMEBUFFER_COMPLETE)); + + m_func->glEnable(GL_MULTISAMPLE); + m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); + m_func->glClear(GL_COLOR_BUFFER_BIT); + m_func->glDisable(GL_MULTISAMPLE); + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); + + // WHEN + m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + + GLuint result[10*10]; + m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); + + // THEN + GLuint v = (0.2f) * 255; + v = v | (v<<8) | (v<<16) | (v<<24); + for (GLuint value : result) { + QCOMPARE(value, v); + } + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + m_func->glDeleteFramebuffers(2, fbos); + m_func->glDeleteTextures(2, fboTextures); + } + +#define ADD_GL_TYPE_ENTRY(Type, Expected) \ + QTest::newRow(#Type) << Type << Expected; + + void uniformTypeFromGLType_data() + { + QTest::addColumn("glType"); + QTest::addColumn("expected"); + + ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); + ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); + ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); + ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); + ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); + } + + void uniformTypeFromGLType() + { + // GIVEN + QFETCH(int, glType); + QFETCH(UniformType, expected); + + // WHEN + UniformType computed = m_glHelper.uniformTypeFromGLType(glType); + + // THEN + QCOMPARE(computed, expected); + } + + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void fenceSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + // THEN + QVERIFY(sync != nullptr); + QCOMPARE(m_func->glIsSync(sync), GL_TRUE); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void clientWaitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + QElapsedTimer t; + t.start(); + + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + m_glHelper.clientWaitSync(sync, 1000000); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + qDebug() << t.nsecsElapsed(); + } + + void waitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void wasSyncSignaled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // Shouldn't loop forever + while (!m_glHelper.wasSyncSignaled(sync)) + ; + } + + void deleteSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_glHelper.clientWaitSync(sync, GLuint64(-1)); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); + + // WHEN + m_glHelper.deleteSync(sync); + + // THEN + QCOMPARE(m_func->glIsSync(sync), GL_FALSE); + } + + void rasterMode() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 3.3 functions not supported"); + + m_func->glGetError(); + m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_POLYGON_MODE, &p); + QCOMPARE(p, GL_LINE); + } + +private: + QScopedPointer m_window; + QOpenGLContext m_glContext; + GraphicsHelperGL3_3 m_glHelper; + QOpenGLFunctions_3_3_Core *m_func = nullptr; + bool m_initializationSuccessful = false; +}; + +#endif + +int main(int argc, char *argv[]) +{ +#ifdef TEST_SHOULD_BE_PERFORMED + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + tst_GraphicsHelperGL3_3 tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +#endif + return 0; +} + +#ifdef TEST_SHOULD_BE_PERFORMED +#include "tst_graphicshelpergl3_3.moc" +#endif diff --git a/tests/auto/render/opengl/graphicshelpergl4/graphicshelpergl4.pro b/tests/auto/render/opengl/graphicshelpergl4/graphicshelpergl4.pro new file mode 100644 index 000000000..5ea881208 --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl4/graphicshelpergl4.pro @@ -0,0 +1,16 @@ +TEMPLATE = app + +TARGET = tst_graphicshelpergl4 + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_graphicshelpergl4.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp new file mode 100644 index 000000000..31024e1db --- /dev/null +++ b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -0,0 +1,2583 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(QT_OPENGL_ES_2) && defined(QT_OPENGL_4_3) + +#define TEST_SHOULD_BE_PERFORMED 1 + +using namespace Qt3DRender; +using namespace Qt3DRender::Render; + +namespace { + +const QByteArray vertCode = QByteArrayLiteral( + "#version 430 core\n" \ + "layout(location = 1) in vec3 vertexPosition;\n" \ + "layout(location = 2) in vec2 vertexTexCoord;\n" \ + "out vec2 texCoord;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vertexTexCoord;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray vertCodeUniformBuffer = QByteArrayLiteral( + "#version 430 core\n" \ + "layout(location = 1) in vec3 vertexPosition;\n" \ + "layout(location = 2) in vec2 vertexTexCoord;\n" \ + "layout(location = 3) in int vertexColorIndex;\n" \ + "layout(location = 4) in double vertexTexCoordScale;\n" \ + "out vec2 texCoord;\n" \ + "flat out int colorIndex;\n" \ + "void main()\n" \ + "{\n" \ + " texCoord = vec2(vertexTexCoordScale * vertexTexCoord);\n" \ + " colorIndex = vertexColorIndex;\n" \ + " gl_Position = vec4(vertexPosition, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeFragOutputs = QByteArrayLiteral( + "#version 430 core\n" \ + "out vec4 color;\n" \ + "out vec2 temp;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0);\n" \ + " temp = vec2(1.0, 0.3);\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloat = QByteArrayLiteral( + "#version 430 core\n" \ + "out vec4 color;\n" \ + "layout(location = 1) uniform float multiplier;\n" \ + "layout(location = 2) uniform vec2 multiplierVec2;\n" \ + "layout(location = 3) uniform vec3 multiplierVec3;\n" \ + "layout(location = 4) uniform vec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " vec4 randomMult = multiplierVec4 + vec4(multiplierVec3, 0.0) + vec4(multiplierVec2, 0.0, 0.0);\n" \ + " color = vec4(1.0, 0.0, 0.0, 1.0) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsInt = QByteArrayLiteral( + "#version 430 core\n" \ + "out ivec4 color;\n" \ + "layout(location = 1) uniform int multiplier;\n" \ + "layout(location = 2) uniform ivec2 multiplierVec2;\n" \ + "layout(location = 3) uniform ivec3 multiplierVec3;\n" \ + "layout(location = 4) uniform ivec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " ivec4 randomMult = multiplierVec4 + ivec4(multiplierVec3, 0) + ivec4(multiplierVec2, 0, 0);\n" \ + " color = ivec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsUInt = QByteArrayLiteral( + "#version 430 core\n" \ + "out uvec4 color;\n" \ + "layout(location = 1) uniform uint multiplier;\n" \ + "layout(location = 2) uniform uvec2 multiplierVec2;\n" \ + "layout(location = 3) uniform uvec3 multiplierVec3;\n" \ + "layout(location = 4) uniform uvec4 multiplierVec4;\n" \ + "void main()\n" \ + "{\n" \ + " uvec4 randomMult = multiplierVec4 + uvec4(multiplierVec3, 0) + uvec4(multiplierVec2, 0, 0);\n" \ + " color = uvec4(1, 0, 0, 1) * randomMult * multiplier;\n" \ + "}\n"); + +const QByteArray fragCodeUniformsFloatMatrices = QByteArrayLiteral( + "#version 430 core\n" \ + "out vec4 color;\n" \ + "layout(location = 1) uniform mat2 m2;\n" \ + "layout(location = 2) uniform mat2x3 m23;\n" \ + "layout(location = 3) uniform mat3x2 m32;\n" \ + "layout(location = 4) uniform mat2x4 m24;\n" \ + "layout(location = 5) uniform mat4x2 m42;\n" \ + "layout(location = 6) uniform mat3 m3;\n" \ + "layout(location = 7) uniform mat3x4 m34;\n" \ + "layout(location = 8) uniform mat4x3 m43;\n" \ + "layout(location = 9) uniform mat4 m4;\n" \ + "void main()\n" \ + "{\n" \ + " float lengthSum = m2[0][0] + m23[0][0] + m32[0][0] + m24[0][0] + m42[0][0] + m3[0][0] + m34[0][0] + m43[0][0] + m4[0][0];\n" \ + " color = vec4(1, 0, 0, 1) * lengthSum;\n" \ + "}\n"); + +const QByteArray fragCodeUniformBuffer = QByteArrayLiteral( + "#version 430 core\n" \ + "out vec4 color;\n" \ + "in vec2 texCoord;\n" \ + "flat in int colorIndex;\n" \ + "layout(binding = 2, std140) uniform ColorArray\n" \ + "{\n" \ + " vec4 colors[256];\n" \ + "};\n" \ + "void main()\n" \ + "{\n" \ + " color = colors[colorIndex] + vec4(texCoord.s, texCoord.t, 0.0, 1.0);\n" \ + "}\n"); + +const QByteArray fragCodeSamplers = QByteArrayLiteral( + "#version 430 core\n" \ + "in vec2 texCoord;\n" \ + "out vec4 color;\n" \ + "layout(location = 1) uniform sampler1D s1;\n" \ + "layout(location = 2) uniform sampler2D s2;\n" \ + "layout(location = 3) uniform sampler2DArray s2a;\n" \ + "layout(location = 4) uniform sampler3D s3;\n" \ + "layout(location = 5) uniform samplerCube scube;\n" \ + "layout(location = 6) uniform sampler2DRect srect;\n" \ + "void main()\n" \ + "{\n" \ + " color = vec4(1, 0, 0, 1) *" \ + " texture(s1, texCoord.x) *" \ + " texture(s2, texCoord) *" \ + " texture(s2a, vec3(texCoord, 0.0)) *" \ + " texture(s3, vec3(texCoord, 0.0)) *" \ + " texture(scube, vec3(texCoord, 0)) *" \ + " texture(srect, texCoord);\n" \ + "}\n"); + +const QByteArray fragCodeImages = QByteArrayLiteral( + "#version 430 core\n" \ + "in vec2 texCoord;\n" \ + "out vec4 color;\n" \ + "layout(location = 1, rgba32f) readonly uniform image1D s1;\n" \ + "layout(location = 2, rg16f) readonly uniform image2D s2;\n" \ + "layout(location = 3, r16f) readonly uniform image2DArray s2a;\n" \ + "layout(location = 4, rg8) readonly uniform image3D s3;\n" \ + "layout(location = 5, rgba16_snorm) readonly uniform imageCube scube;\n" \ + "layout(location = 6, rg16) readonly uniform image2DRect srect;\n" \ + "void main()\n" \ + "{\n" \ + " ivec2 coords = ivec2(texCoord);\n"\ + " color = vec4(1, 0, 0, 1) *" \ + " imageLoad(s1, coords.x) *" \ + " imageLoad(s2, coords) *" \ + " imageLoad(s2a, ivec3(coords, 0)) *" \ + " imageLoad(s3, ivec3(coords, 0)) *" \ + " imageLoad(scube, ivec3(coords, 0)) *" \ + " imageLoad(srect, coords);\n" \ + "}\n"); + +const QByteArray computeShader = QByteArrayLiteral( + "#version 430 core\n" \ + "uniform float particleStep;\n" \ + "uniform float finalCollisionFactor;\n" \ + "layout (local_size_x = 1024) in;\n" \ + "struct ParticleData\n" \ + "{\n" \ + " vec4 position;\n" \ + " vec4 direction;\n" \ + " vec4 color;\n" \ + "};\n" \ + "layout (std140, binding = 6) coherent buffer Particles\n" \ + "{\n" \ + " ParticleData particles[];\n" \ + "} data;\n" \ + "void main(void)\n" \ + "{\n" \ + " uint globalId = gl_GlobalInvocationID.x;\n" \ + " ParticleData currentParticle = data.particles[globalId];\n" \ + " currentParticle.position = currentParticle.position + currentParticle.direction * particleStep;\n" \ + " vec4 acceleration = normalize(vec4(0.0) - currentParticle.position) * finalCollisionFactor;\n" \ + " currentParticle.direction = currentParticle.direction + acceleration * particleStep;\n" \ + " data.particles[globalId] = currentParticle;\n" \ + "}"); + +} // anonymous + +class tst_GraphicsHelperGL4 : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void init() + { + m_window.reset(new QWindow); + m_window->setSurfaceType(QWindow::OpenGLSurface); + m_window->setGeometry(0, 0, 10, 10); + + QSurfaceFormat format; + format.setVersion(4, 3); + format.setProfile(QSurfaceFormat::CoreProfile); + format.setDepthBufferSize(24); + format.setSamples(4); + format.setStencilBufferSize(8); + m_window->setFormat(format); + m_glContext.setFormat(format); + + m_window->create(); + + if (!m_glContext.create()) { + qWarning() << "Failed to create OpenGL context"; + return; + } + + if (!m_glContext.makeCurrent(m_window.data())) { + qWarning() << "Failed to make OpenGL context current"; + return; + } + + if ((m_func = m_glContext.versionFunctions()) != nullptr) { + m_glHelper.initializeHelper(&m_glContext, m_func); + m_initializationSuccessful = true; + } + } + + void cleanup() + { + m_glContext.doneCurrent(); + } + + void alphaTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + // Deprecated + } + + void bindBufferBase() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint bufferId = 0; + // WHEN + m_func->glGenBuffers(1, &bufferId); + // THEN + QVERIFY(bufferId != 0); + + + // WHEN + m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, bufferId); + m_glHelper.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, bufferId); + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundToPointBufferId = 0; + m_func->glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, 2, &boundToPointBufferId); + QVERIFY(boundToPointBufferId == GLint(bufferId)); + + // Restore to sane state + m_func->glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0); + m_func->glDeleteBuffers(1, &bufferId); + } + + void bindFragDataLocation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // WHEN + QHash fragLocations; + fragLocations.insert(QStringLiteral("temp"), 2); + fragLocations.insert(QStringLiteral("color"), 1); + m_glHelper.bindFragDataLocation(shaderProgram.programId(), fragLocations); + + // THEN + QVERIFY(shaderProgram.link()); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + const GLint tempLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "temp"); + const GLint colorLocation = m_func->glGetFragDataLocation(shaderProgram.programId(), "color"); + QCOMPARE(tempLocation, 2); + QCOMPARE(colorLocation, 1); + } + + void bindFrameBufferAttachment() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + { + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color2; + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureAttachmentId = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0 + 2, + GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, + &textureAttachmentId); + QCOMPARE(GLuint(textureAttachmentId), texture.textureId()); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::TargetCubeMap); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + { // Check All Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_TRUE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { // Check Specific Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + GLint textureFace = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, + &textureFace); + QCOMPARE(textureFace, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, + &textureIsLayered); + QCOMPARE(textureIsLayered, GL_FALSE); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + } + } + + void bindFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBODraw); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint boundindFBOId = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBORead); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // WHEN + m_glHelper.bindFrameBufferObject(fboId, GraphicsHelperInterface::FBOReadAndDraw); + + // THEN + error = m_func->glGetError(); + QVERIFY(error == 0); + boundindFBOId = 0; + m_func->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundindFBOId); + QVERIFY(GLuint(boundindFBOId) == fboId); + + // Cleanup + m_func->glDeleteFramebuffers(1, &fboId); + } + + void bindImageTexture() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // THEN + QVERIFY(texture.textureId() != 0 && texture.isCreated() && texture.isStorageAllocated()); + + // WHEN + m_glHelper.bindImageTexture(0, + texture.textureId(), + 0, + GL_FALSE, + 0, + GL_READ_WRITE, + GL_RGBA8UI); + + // THEN + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void bindShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Compute, computeShader); + QVERIFY(shaderProgram.link()); + + // WHEN + GLint index = m_func->glGetProgramResourceIndex(shaderProgram.programId(), + GL_SHADER_STORAGE_BLOCK, + "Particles"); + // THEN + GLint binding = -1; + GLenum prop = GL_BUFFER_BINDING; + m_func->glGetProgramResourceiv(shaderProgram.programId(), + GL_SHADER_STORAGE_BLOCK, + index, + 1, &prop, + 4, NULL, &binding); + QCOMPARE(binding, 6); + + // WHEN + m_glHelper.bindShaderStorageBlock(shaderProgram.programId(), index, 1); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + m_func->glGetProgramResourceiv(shaderProgram.programId(), + GL_SHADER_STORAGE_BLOCK, + index, + 1, &prop, + 4, NULL, &binding); + QCOMPARE(binding, 1); + } + + void bindUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + GLint index = m_func->glGetUniformBlockIndex(shaderProgram.programId(), "ColorArray"); + m_glHelper.bindUniformBlock(shaderProgram.programId(), index, 1); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void blendEquation() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLint equation = 0; + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_ADD); + + // WHEN + m_glHelper.blendEquation(GL_FUNC_REVERSE_SUBTRACT); + + // THEN + m_func->glGetIntegerv(GL_BLEND_EQUATION_RGB, &equation); + QCOMPARE(equation, GL_FUNC_REVERSE_SUBTRACT); + } + + void blendFunci() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLint destinationRgb = 0; + GLint destinationAlpha = 0; + GLint sourceRgb = 0; + GLint sourceAlpha = 0; + m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 4, &sourceRgb); + m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 4, &destinationRgb); + m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 4, &sourceAlpha); + m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 4, &destinationAlpha); + + // THEN + QCOMPARE(destinationAlpha, GL_ZERO); + QCOMPARE(destinationRgb, GL_ZERO); + QCOMPARE(sourceRgb, GL_ONE); + QCOMPARE(sourceAlpha, GL_ONE); + + // WHEN + m_glHelper.blendFunci(4, GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA); + + m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 4, &sourceRgb); + m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 4, &destinationRgb); + m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 4, &sourceAlpha); + m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 4, &destinationAlpha); + + // THEN + QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA); + QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_ALPHA); + QCOMPARE(sourceRgb, GL_SRC_COLOR); + QCOMPARE(sourceAlpha, GL_SRC_COLOR); + + // Reset default + m_glHelper.blendFunci(4, GL_ONE, GL_ZERO); + } + + void blendFuncSeparatei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLint destinationRgb = 0; + GLint destinationAlpha = 0; + GLint sourceRgb = 0; + GLint sourceAlpha = 0; + m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 2, &sourceRgb); + m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 2, &destinationRgb); + m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 2, &sourceAlpha); + m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 2, &destinationAlpha); + + // THEN + QCOMPARE(destinationAlpha, GL_ZERO); + QCOMPARE(destinationRgb, GL_ZERO); + QCOMPARE(sourceRgb, GL_ONE); + QCOMPARE(sourceAlpha, GL_ONE); + + // WHEN + m_glHelper.blendFuncSeparatei(2, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_func->glGetIntegeri_v(GL_BLEND_SRC_RGB, 2, &sourceRgb); + m_func->glGetIntegeri_v(GL_BLEND_DST_RGB, 2, &destinationRgb); + m_func->glGetIntegeri_v(GL_BLEND_SRC_ALPHA, 2, &sourceAlpha); + m_func->glGetIntegeri_v(GL_BLEND_DST_ALPHA, 2, &destinationAlpha); + + // THEN + QCOMPARE(destinationAlpha, GL_ONE_MINUS_SRC_ALPHA); + QCOMPARE(destinationRgb, GL_ONE_MINUS_SRC_COLOR); + QCOMPARE(sourceRgb, GL_SRC_COLOR); + QCOMPARE(sourceAlpha, GL_SRC_ALPHA); + + // Reset default + m_glHelper.blendFunci(4, GL_ONE, GL_ZERO); + } + + void boundFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + // THEN + GLint boundBuffer = 0; + m_func->glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &boundBuffer); + QCOMPARE(GLuint(boundBuffer), fboId); + + // THEN + QCOMPARE(m_glHelper.boundFrameBufferObject(), fboId); + + // Reset state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void checkFrameBufferComplete() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color1; + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + QVERIFY(m_glHelper.checkFrameBufferComplete()); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + + void clearBufferf() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + // Create 4 attachments + QOpenGLTexture *textures[4]; + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // Set Draw buffers + GLenum clearBufferEnum = GL_COLOR_ATTACHMENT3; + m_func->glDrawBuffers(1, &clearBufferEnum); + + const GLint bufferIndex = 0; // index of the element in the draw buffers + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // WHEN + const QVector4D clearValue1 = QVector4D(0.5f, 0.2f, 0.4f, 0.8f); + m_func->glClearBufferfv(GL_COLOR, bufferIndex, reinterpret_cast(&clearValue1)); + error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + QVector colors(512 * 512); + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + + for (const QVector4D c : colors) { + QVERIFY(c == clearValue1); + } + + // WHEN + const QVector4D clearValue2 = QVector4D(0.4f, 0.5f, 0.4f, 1.0f); + m_glHelper.clearBufferf(bufferIndex, clearValue2); + + // THEN + textures[3]->bind(); + m_func->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, colors.data()); + textures[3]->release(); + for (const QVector4D c : colors) { + QVERIFY(c == clearValue2); + } + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void createFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // WHEN + const GLuint fboId = m_glHelper.createFrameBufferObject(); + + // THEN + QVERIFY(fboId != 0); + + // Restore + m_func->glDeleteFramebuffers(1, &fboId); + } + + void depthMask() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLboolean depthWritingEnabled = false; + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + + // THEN + QVERIFY(depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_FALSE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(!depthWritingEnabled); + + // WHEN + m_glHelper.depthMask(GL_TRUE); + + // THEN + m_func->glGetBooleanv(GL_DEPTH_WRITEMASK, &depthWritingEnabled); + QVERIFY(depthWritingEnabled); + } + + void depthTest() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_DEPTH_TEST); + m_func->glDepthFunc(GL_LESS); + + // WHEN + m_glHelper.depthTest(GL_LEQUAL); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + GLint depthMode = 0; + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LEQUAL); + + // WHEN + m_glHelper.depthTest(GL_LESS); + QVERIFY(m_func->glIsEnabled(GL_DEPTH_TEST)); + m_func->glGetIntegerv(GL_DEPTH_FUNC, &depthMode); + QCOMPARE(depthMode, GL_LESS); + } + + void disableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_CLIP_DISTANCE0 + 5); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + + // WHEN + m_glHelper.disableClipPlane(5); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 5)); + } + + void disablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glEnablei(GL_BLEND, 2); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 2)); + + // WHEN + m_glHelper.disablei(GL_BLEND, 2); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 2)); + } + + void disablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.disablePrimitiveRestart(); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + } + + void drawBuffers() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + QOpenGLTexture *textures[4]; + + // Create 4 attachments + for (int i = 0; i < 4; ++i) { + Attachment attachment; + attachment.m_point = static_cast(i); + + QOpenGLTexture *texture = new QOpenGLTexture(QOpenGLTexture::Target2D); + textures[i] = texture; + texture->setSize(512, 512); + texture->setFormat(QOpenGLTexture::RGBA32F); + texture->setMinificationFilter(QOpenGLTexture::Linear); + texture->setMagnificationFilter(QOpenGLTexture::Linear); + texture->setWrapMode(QOpenGLTexture::ClampToEdge); + if (!texture->create()) + qWarning() << "Texture creation failed"; + texture->allocateStorage(); + QVERIFY(texture->isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + m_glHelper.bindFrameBufferAttachment(texture, attachment); + } + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + // WHEN + GLenum bufferEnum = GL_COLOR_ATTACHMENT4; + m_func->glDrawBuffers(1, &bufferEnum); + + // THEN + GLint enumValue = -1; + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT4); + + // WHEN + GLint newBufferEnum = 2; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // WHEN + newBufferEnum = 0; + m_glHelper.drawBuffers(1, &newBufferEnum); + + // THEN + m_func->glGetIntegerv(GL_DRAW_BUFFER0, &enumValue); + QCOMPARE(enumValue, GL_COLOR_ATTACHMENT0 + newBufferEnum); + + // Restore + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + for (int i = 0; i < 4; ++i) + delete textures[i]; + } + + void enableClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_CLIP_DISTANCE0 + 4); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + + // WHEN + m_glHelper.enableClipPlane(4); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_CLIP_DISTANCE0 + 4)); + } + + void enablei() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisablei(GL_BLEND, 4); + + // THEN + QVERIFY(!m_func->glIsEnabledi(GL_BLEND, 4)); + + // WHEN + m_glHelper.enablei(GL_BLEND, 4); + + // THEN + QVERIFY(m_func->glIsEnabledi(GL_BLEND, 4)); + } + + void enablePrimitiveRestart() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_PRIMITIVE_RESTART); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + + // WHEN + m_glHelper.enablePrimitiveRestart(883); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PRIMITIVE_RESTART)); + GLint restartIndex = 0; + m_func->glGetIntegerv(GL_PRIMITIVE_RESTART_INDEX, &restartIndex); + QCOMPARE(restartIndex, 883); + + // Restore + m_func->glDisable(GL_PRIMITIVE_RESTART); + } + + void enableVertexAttribute() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + shaderProgram.bind(); + + // WHEN + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void frontFace() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glFrontFace(GL_CW); + + // THEN + GLint face = 0; + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CW); + + // WHEN + m_glHelper.frontFace(GL_CCW); + + // THEN + m_func->glGetIntegerv(GL_FRONT_FACE, &face); + QCOMPARE(face, GL_CCW); + } + + void getRenderBufferDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint renderBufferId = 0; + m_func->glGenRenderbuffers(1, &renderBufferId); + QVERIFY(renderBufferId != 0); + + // WHEN + m_func->glBindRenderbuffer(GL_RENDERBUFFER, renderBufferId); + m_func->glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 512, 512); + m_func->glBindRenderbuffer(GL_RENDERBUFFER, 0); + const QSize dimensions = m_glHelper.getRenderBufferDimensions(renderBufferId); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + + // Restore + m_func->glDeleteRenderbuffers(1, &renderBufferId); + } + + void getTextureDimensions() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::Target2D); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA8U); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.create(); + texture.allocateStorage(); + + // WHEN + const QSize dimensions = m_glHelper.getTextureDimensions(texture.textureId(), GL_TEXTURE_2D); + + // THEN + QCOMPARE(dimensions, QSize(512, 512)); + } + + void pointSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glEnable(GL_PROGRAM_POINT_SIZE); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + GLfloat size = 0; + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 1.0f); + + // WHEN + m_glHelper.pointSize(false, 0.5f); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_PROGRAM_POINT_SIZE)); + m_func->glGetFloatv(GL_POINT_SIZE, &size); + QCOMPARE(size, 0.5f); + } + + void maxClipPlaneCount() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLint maxCount = -1; + m_func->glGetIntegerv(GL_MAX_CLIP_PLANES, &maxCount); + + // THEN + QCOMPARE(maxCount, m_glHelper.maxClipPlaneCount()); + } + + void programUniformBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector activeUniformBlocks = m_glHelper.programUniformBlocks(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniformBlocks.size(), 1); + const ShaderUniformBlock uniformBlock = activeUniformBlocks.first(); + + QCOMPARE(uniformBlock.m_activeUniformsCount, 1); + QCOMPARE(uniformBlock.m_name, QStringLiteral("ColorArray")); + QCOMPARE(uniformBlock.m_binding, 2); + } + + void programAttributesAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeSamplers); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeAttributes = m_glHelper.programAttributesAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeAttributes.size(), 2); + std::sort(activeAttributes.begin(), activeAttributes.end(), [] (const ShaderAttribute &a, const ShaderAttribute &b) { return a.m_location < b.m_location; }); + + const ShaderAttribute attribute1 = activeAttributes.at(0); + QCOMPARE(attribute1.m_name, QStringLiteral("vertexPosition")); + QCOMPARE(attribute1.m_size, 1); + QCOMPARE(attribute1.m_location, 1); + QCOMPARE(attribute1.m_type, GLenum(GL_FLOAT_VEC3)); + + const ShaderAttribute attribute2 = activeAttributes.at(1); + QCOMPARE(attribute2.m_name, QStringLiteral("vertexTexCoord")); + QCOMPARE(attribute2.m_size, 1); + QCOMPARE(attribute2.m_location, 2); + QCOMPARE(attribute2.m_type, GLenum(GL_FLOAT_VEC2)); + } + + void programUniformsAndLocations() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + + // THEN + QCOMPARE(activeUniforms.size(), 4); + std::sort(activeUniforms.begin(), activeUniforms.end(), [] (const ShaderUniform &a, const ShaderUniform &b) { return a.m_location < b.m_location; }); + + const ShaderUniform uniform1 = activeUniforms.at(0); + QCOMPARE(uniform1.m_location, 1); + QCOMPARE(uniform1.m_offset, -1); + QCOMPARE(uniform1.m_blockIndex, -1); + QCOMPARE(uniform1.m_arrayStride, -1); + QCOMPARE(uniform1.m_matrixStride, -1); + QCOMPARE(uniform1.m_size, 1); + QCOMPARE(uniform1.m_type, GLenum(GL_FLOAT)); + QCOMPARE(uniform1.m_name, QStringLiteral("multiplier")); + + const ShaderUniform uniform2 = activeUniforms.at(1); + QCOMPARE(uniform2.m_location, 2); + QCOMPARE(uniform2.m_offset, -1); + QCOMPARE(uniform2.m_blockIndex, -1); + QCOMPARE(uniform2.m_arrayStride, -1); + QCOMPARE(uniform2.m_matrixStride, -1); + QCOMPARE(uniform2.m_size, 1); + QCOMPARE(uniform2.m_type, GLenum(GL_FLOAT_VEC2)); + QCOMPARE(uniform2.m_name, QStringLiteral("multiplierVec2")); + + const ShaderUniform uniform3 = activeUniforms.at(2); + QCOMPARE(uniform3.m_location, 3); + QCOMPARE(uniform3.m_offset, -1); + QCOMPARE(uniform3.m_blockIndex, -1); + QCOMPARE(uniform3.m_arrayStride, -1); + QCOMPARE(uniform3.m_matrixStride, -1); + QCOMPARE(uniform3.m_size, 1); + QCOMPARE(uniform3.m_type, GLenum(GL_FLOAT_VEC3)); + QCOMPARE(uniform3.m_name, QStringLiteral("multiplierVec3")); + + const ShaderUniform uniform4 = activeUniforms.at(3); + QCOMPARE(uniform4.m_location, 4); + QCOMPARE(uniform4.m_offset, -1); + QCOMPARE(uniform4.m_blockIndex, -1); + QCOMPARE(uniform4.m_arrayStride, -1); + QCOMPARE(uniform4.m_matrixStride, -1); + QCOMPARE(uniform4.m_size, 1); + QCOMPARE(uniform4.m_type, GLenum(GL_FLOAT_VEC4)); + QCOMPARE(uniform4.m_name, QStringLiteral("multiplierVec4")); + } + + void programShaderStorageBlock() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Compute, computeShader); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector activeShaderStorageBlocks = m_glHelper.programShaderStorageBlocks(shaderProgram.programId()); + + // THEN + QVERIFY(activeShaderStorageBlocks.size() == 1); + ShaderStorageBlock block = activeShaderStorageBlocks.first(); + QCOMPARE(block.m_name, QStringLiteral("Particles")); + QCOMPARE(block.m_activeVariablesCount, 3); + QCOMPARE(block.m_index, 0); + QCOMPARE(block.m_binding, 6); + QCOMPARE(block.m_size, (4 + 4 + 4) * 4); + } + + void releaseFrameBufferObject() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_glHelper.releaseFrameBufferObject(fboId); + + // THEN + QVERIFY(!m_func->glIsFramebuffer(fboId)); + } + + void setMSAAEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_MULTISAMPLE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_MULTISAMPLE)); + + // WHEN + m_glHelper.setMSAAEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_MULTISAMPLE)); + } + + void setAlphaCoverageEnabled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + + // WHEN + m_glHelper.setAlphaCoverageEnabled(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE)); + } + + void setClipPlane() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + // Deprecated in GL 4 + } + + void setSeamlessCubemap() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + + void setVerticesPerPatch() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + m_func->glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(true); + + // THEN + QVERIFY(m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + + // WHEN + m_glHelper.setSeamlessCubemap(false); + + // THEN + QVERIFY(!m_func->glIsEnabled(GL_TEXTURE_CUBE_MAP_SEAMLESS)); + } + + void supportsFeature() + { + for (int i = 0; i <= GraphicsHelperInterface::Fences; ++i) + QVERIFY(m_glHelper.supportsFeature(static_cast(i))); + } + + +#define ADD_UNIFORM_ENTRY(FragShader, Type, Location, ComponentSize, ExpectedRawSize) \ + QTest::newRow(#FragShader"_"#Type) << FragShader << Type << Location << ComponentSize << ExpectedRawSize; + + void uniformsByteSize_data() + { + QTest::addColumn("fragShader"); + QTest::addColumn("type"); + QTest::addColumn("location"); + QTest::addColumn("componentSize"); + QTest::addColumn("expectedByteSize"); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT, 1, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC2, 2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC3, 3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloat, GL_FLOAT_VEC4, 4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT, 1, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC2, 2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC3, 3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsInt, GL_INT_VEC4, 4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT, 1, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC2, 2, 1, 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC3, 3, 1, 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsUInt, GL_UNSIGNED_INT_VEC4, 4, 1, 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2, 1, 1, 4 * 2 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x3, 2, 1, 4 * 2 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x2, 3, 1, 4 * 3 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT2x4, 4, 1, 4 * 2 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x2, 5, 1, 4 * 4 * 2); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3, 6, 1, 4 * 3 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT3x4, 7, 1, 4 * 3 * 4); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4x3, 8, 1, 4 * 4 * 3); + ADD_UNIFORM_ENTRY(fragCodeUniformsFloatMatrices, GL_FLOAT_MAT4, 9, 1, 4 * 4 * 4); + + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_1D, 1, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D, 2, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_ARRAY, 3, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_3D, 4, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_CUBE, 5, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeSamplers, GL_SAMPLER_2D_RECT, 6, 1, 4); + + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_1D, 1, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D, 2, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_ARRAY, 3, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_3D, 4, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_CUBE, 5, 1, 4); + ADD_UNIFORM_ENTRY(fragCodeImages, GL_IMAGE_2D_RECT, 6, 1, 4); + } + + void uniformsByteSize() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QFETCH(QByteArray, fragShader); + QFETCH(int, type); + QFETCH(int, location); + QFETCH(int, componentSize); + QFETCH(int, expectedByteSize); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShader); + QVERIFY(shaderProgram.link()); + + // WHEN + const QVector activeUniforms = m_glHelper.programUniformsAndLocations(shaderProgram.programId()); + ShaderUniform matchingUniform; + for (const ShaderUniform &u : activeUniforms) { + if (u.m_location == location) { + matchingUniform = u; + break; + } + } + + // THEN + QCOMPARE(matchingUniform.m_location, location); + QCOMPARE(matchingUniform.m_type, GLuint(type)); + QCOMPARE(matchingUniform.m_size, componentSize); + + // WHEN + const int computedRawByteSize = m_glHelper.uniformByteSize(matchingUniform); + + // THEN + QCOMPARE(expectedByteSize, computedRawByteSize); + + // Restore + m_func->glUseProgram(0); + } + + void useProgram() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeFragOutputs); + + // THEN + QVERIFY(shaderProgram.link()); + + GLint currentProg = 0; + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + + // WHEN + m_glHelper.useProgram(shaderProgram.programId()); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QCOMPARE(GLuint(currentProg), shaderProgram.programId()); + + // WHEN + m_glHelper.useProgram(0); + + // THEN + m_func->glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProg); + QVERIFY(currentProg == 0); + } + + void vertexAttribDivisor() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + } + + void vertexAttributePointer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLVertexArrayObject vao; + vao.create(); + QOpenGLVertexArrayObject::Binder binder(&vao); + + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCodeUniformBuffer); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformBuffer); + QVERIFY(shaderProgram.link()); + + GLint positionLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexPosition"); + GLint texCoordLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoord"); + GLint colorIndexLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexColorIndex"); + GLint texCoordScaleLocation = m_func->glGetAttribLocation(shaderProgram.programId(), "vertexTexCoordScale"); + + const int vertexCount = 99; + QOpenGLBuffer positionBuffer(QOpenGLBuffer::VertexBuffer); + positionBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + positionBuffer.create(); + positionBuffer.bind(); + positionBuffer.allocate(vertexCount * sizeof(QVector3D)); + + QOpenGLBuffer texCoordBuffer(QOpenGLBuffer::VertexBuffer); + texCoordBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + texCoordBuffer.create(); + texCoordBuffer.allocate(vertexCount * sizeof(QVector2D)); + + QOpenGLBuffer colorIndexBuffer(QOpenGLBuffer::VertexBuffer); + colorIndexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + colorIndexBuffer.create(); + colorIndexBuffer.allocate(vertexCount * sizeof(int)); + + QOpenGLBuffer scaleBuffer(QOpenGLBuffer::VertexBuffer); + scaleBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + scaleBuffer.create(); + scaleBuffer.allocate(vertexCount * sizeof(double)); + + // WHEN + shaderProgram.bind(); + positionBuffer.bind(); + m_glHelper.enableVertexAttributeArray(positionLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC3, positionLocation, 3, GL_FLOAT, GL_TRUE, 0, 0); + + texCoordBuffer.bind(); + m_glHelper.enableVertexAttributeArray(texCoordLocation); + m_glHelper.vertexAttributePointer(GL_FLOAT_VEC2, texCoordLocation, 2, GL_FLOAT, GL_TRUE, 0, 0); + + colorIndexBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_INT, colorIndexLocation, 1, GL_INT, GL_TRUE, 0, 0); + + scaleBuffer.bind(); + m_glHelper.enableVertexAttributeArray(colorIndexLocation); + m_glHelper.vertexAttributePointer(GL_DOUBLE, texCoordScaleLocation, 1, GL_DOUBLE, GL_TRUE, 0, 0); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void glUniform1fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat value = 883.0f; + m_glHelper.glUniform1fv(1, 1, &value); + + // THEN + GLfloat setValue = 0.0f; + m_func->glGetUniformfv(shaderProgram.programId(), 1, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[2] = { 383.0f, 427.0f }; + m_glHelper.glUniform2fv(2, 1, values); + + // THEN + GLfloat setValues[2] = { 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 2, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[3] = { 572.0f, 1340.0f, 1584.0f }; + m_glHelper.glUniform3fv(3, 1, values); + + // THEN + GLfloat setValues[3] = { 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 3, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloat); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + m_glHelper.glUniform4fv(4, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 4, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(setValues[i], values[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint value = 883; + m_glHelper.glUniform1iv(1, 1, &value); + + // THEN + GLint setValue = 0; + m_func->glGetUniformiv(shaderProgram.programId(), 1, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[2] = { 383, 427 }; + m_glHelper.glUniform2iv(2, 1, values); + + // THEN + GLint setValues[2] = { 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), 2, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[3] = { 572, 1340, 1584 }; + m_glHelper.glUniform3iv(3, 1, values); + + // THEN + GLint setValues[3] = { 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), 3, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4iv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLint values[4] = { 454, 350, 883, 355 }; + m_glHelper.glUniform4iv(4, 1, values); + + // THEN + GLint setValues[4] = { 0, 0, 0, 0 }; + m_func->glGetUniformiv(shaderProgram.programId(), 4, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform1uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint value = 883U; + m_glHelper.glUniform1uiv(1, 1, &value); + + // THEN + GLuint setValue = 0U; + m_func->glGetUniformuiv(shaderProgram.programId(), 1, &setValue); + QCOMPARE(value, setValue); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform2uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[2] = { 383U, 427U }; + m_glHelper.glUniform2uiv(2, 1, values); + + // THEN + GLuint setValues[2] = { 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), 2, setValues); + for (int i = 0; i < 2; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform3uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[3] = { 572U, 1340U, 1584U }; + m_glHelper.glUniform3uiv(3, 1, values); + + // THEN + GLuint setValues[3] = { 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), 3, setValues); + for (int i = 0; i < 3; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniform4uiv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsUInt); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLuint values[4] = { 454U, 350U, 883U, 355U }; + m_glHelper.glUniform4uiv(4, 1, values); + + // THEN + GLuint setValues[4] = { 0U, 0U, 0U, 0U }; + m_func->glGetUniformuiv(shaderProgram.programId(), 4, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[4] = { 454.0f, 350.0f, 883.0f, 355.0f }; + m_glHelper.glUniformMatrix2fv(1, 1, values); + + // THEN + GLfloat setValues[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 1, setValues); + for (int i = 0; i < 4; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[9] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f }; + m_glHelper.glUniformMatrix3fv(6, 1, values); + + // THEN + GLfloat setValues[9] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 6, setValues); + for (int i = 0; i < 9; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[16] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f, 1200.0f, 427.0f, 396.0f, 1603.0f, 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 327.0f }; + m_glHelper.glUniformMatrix4fv(9, 1, values); + + // THEN + GLfloat setValues[16] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 9, setValues); + for (int i = 0; i < 16; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + m_glHelper.glUniformMatrix2x3fv(2, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 2, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[6] = { 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + m_glHelper.glUniformMatrix3x2fv(3, 1, values); + + // THEN + GLfloat setValues[6] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 3, setValues); + for (int i = 0; i < 6; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix2x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + m_glHelper.glUniformMatrix2x4fv(4, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 4, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x2fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[8] = { 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + m_glHelper.glUniformMatrix4x2fv(5, 1, values); + + // THEN + GLfloat setValues[8] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 5, setValues); + for (int i = 0; i < 8; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix3x4fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 5.3f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f,}; + m_glHelper.glUniformMatrix3x4fv(7, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 7, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + void glUniformMatrix4x3fv() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + QOpenGLShaderProgram shaderProgram; + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertCode); + shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragCodeUniformsFloatMatrices); + QVERIFY(shaderProgram.link()); + + // WHEN + m_func->glUseProgram(shaderProgram.programId()); + GLfloat values[12] = { 55.0f, 5.7f, 383.0f, 6.2f, 383.0f, 427.0f, 454.0f, 350.0f, 883.0f, 355.0f, 1340.0f, 1584.0f}; + m_glHelper.glUniformMatrix4x3fv(8, 1, values); + + // THEN + GLfloat setValues[12] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }; + m_func->glGetUniformfv(shaderProgram.programId(), 8, setValues); + for (int i = 0; i < 12; ++i) + QCOMPARE(values[i], setValues[i]); + + // Restore + m_func->glUseProgram(0); + } + + + void blitFramebuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + // GIVEN + GLuint fbos[2]; + GLuint fboTextures[2]; + + m_func->glGenFramebuffers(2, fbos); + m_func->glGenTextures(2, fboTextures); + + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, fboTextures[0]); + m_func->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 10, 10, true); + m_func->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); + + m_func->glBindTexture(GL_TEXTURE_2D, fboTextures[1]); + m_func->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 10, 10, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); + m_func->glBindTexture(GL_TEXTURE_2D, 0); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[1], 0); + + GLenum status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + m_func->glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); + m_func->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextures[0], 0); + + status = m_func->glCheckFramebufferStatus(GL_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + m_func->glEnable(GL_MULTISAMPLE); + m_func->glClearColor(0.2f, 0.2f, 0.2f, 0.2f); + m_func->glClear(GL_COLOR_BUFFER_BIT); + m_func->glDisable(GL_MULTISAMPLE); + + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); + + // WHEN + m_glHelper.blitFramebuffer(0,0,10,10,0,0,10,10, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[1]); + + GLuint result[10*10]; + m_func->glReadPixels(0,0,10,10,GL_RGBA, GL_UNSIGNED_BYTE, result); + + // THEN + GLuint v = (0.2f) * 255; + v = v | (v<<8) | (v<<16) | (v<<24); + for (GLuint value : result) { + QCOMPARE(value, v); + } + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + + m_func->glDeleteFramebuffers(2, fbos); + m_func->glDeleteTextures(2, fboTextures); + } + +#define ADD_GL_TYPE_ENTRY(Type, Expected) \ + QTest::newRow(#Type) << Type << Expected; + + void uniformTypeFromGLType_data() + { + QTest::addColumn("glType"); + QTest::addColumn("expected"); + + ADD_GL_TYPE_ENTRY(GL_FLOAT, UniformType::Float); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC2, UniformType::Vec2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_VEC3, UniformType::Vec3); + ADD_GL_TYPE_ENTRY(GL_INT, UniformType::Int); + ADD_GL_TYPE_ENTRY(GL_INT_VEC2, UniformType::IVec2); + ADD_GL_TYPE_ENTRY(GL_INT_VEC3, UniformType::IVec3); + ADD_GL_TYPE_ENTRY(GL_INT_VEC4, UniformType::IVec4); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT, UniformType::UInt); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC2, UniformType::UIVec2); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC3, UniformType::UIVec3); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_VEC4, UniformType::UIVec4); + ADD_GL_TYPE_ENTRY(GL_BOOL, UniformType::Bool); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC2, UniformType::BVec2); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC3, UniformType::BVec3); + ADD_GL_TYPE_ENTRY(GL_BOOL_VEC4, UniformType::BVec4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2, UniformType::Mat2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3, UniformType::Mat3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4, UniformType::Mat4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x3, UniformType::Mat2x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT2x4, UniformType::Mat2x4); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x2, UniformType::Mat3x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x2, UniformType::Mat4x2); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT4x3, UniformType::Mat4x3); + ADD_GL_TYPE_ENTRY(GL_FLOAT_MAT3x4, UniformType::Mat3x4); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_1D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_RECT, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_2D_ARRAY_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_1D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_3D, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_BUFFER, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY, UniformType::Sampler); + ADD_GL_TYPE_ENTRY(GL_IMAGE_1D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_2D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_3D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_RECT, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_BUFFER, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_1D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D, UniformType::Image); ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_3D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_RECT, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_BUFFER, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_1D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_3D, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_RECT, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_BUFFER, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_1D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE, UniformType::Image); + ADD_GL_TYPE_ENTRY(GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY, UniformType::Image); + } + + void uniformTypeFromGLType() + { + // GIVEN + QFETCH(int, glType); + QFETCH(UniformType, expected); + + // WHEN + UniformType computed = m_glHelper.uniformTypeFromGLType(glType); + + // THEN + QCOMPARE(computed, expected); + } + + void drawBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.drawBuffer(GL_FRONT); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // THEN + GLint p; + m_func->glGetIntegerv(GL_DRAW_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void readBuffer() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + m_glHelper.readBuffer(GL_FRONT); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_READ_BUFFER, &p); + QCOMPARE(p, GL_FRONT); + } + + void fenceSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + // THEN + QVERIFY(sync != nullptr); + QCOMPARE(m_func->glIsSync(sync), GL_TRUE); + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void clientWaitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + QElapsedTimer t; + t.start(); + + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + + m_glHelper.clientWaitSync(sync, 1000000); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + qDebug() << t.nsecsElapsed(); + } + + void waitSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + } + + void wasSyncSignaled() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_func->glFlush(); + m_glHelper.waitSync(sync); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + // Shouldn't loop forever + while (!m_glHelper.wasSyncSignaled(sync)) + ; + } + + void deleteSync() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 Core functions not supported"); + + m_func->glGetError(); + + // WHEN + GLsync sync = reinterpret_cast(m_glHelper.fenceSync()); + m_glHelper.clientWaitSync(sync, GLuint64(-1)); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + QVERIFY(m_glHelper.wasSyncSignaled(sync) == true); + + // WHEN + m_glHelper.deleteSync(sync); + + // THEN + QCOMPARE(m_func->glIsSync(sync), GL_FALSE); + } + + void rasterMode() + { + if (!m_initializationSuccessful) + QSKIP("Initialization failed, OpenGL 4.3 functions not supported"); + + m_func->glGetError(); + m_glHelper.rasterMode(GL_FRONT_AND_BACK, GL_LINE); + + // THEN + const GLint error = m_func->glGetError(); + QVERIFY(error == 0); + GLint p; + m_func->glGetIntegerv(GL_POLYGON_MODE, &p); + QCOMPARE(p, GL_LINE); + } + +private: + QScopedPointer m_window; + QOpenGLContext m_glContext; + GraphicsHelperGL4 m_glHelper; + QOpenGLFunctions_4_3_Core *m_func = nullptr; + bool m_initializationSuccessful = false; +}; + +#endif + +int main(int argc, char *argv[]) +{ +#ifdef TEST_SHOULD_BE_PERFORMED + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + tst_GraphicsHelperGL4 tc; + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +#endif + return 0; +} + +#ifdef TEST_SHOULD_BE_PERFORMED +#include "tst_graphicshelpergl4.moc" +#endif diff --git a/tests/auto/render/opengl/materialparametergathererjob/materialparametergathererjob.pro b/tests/auto/render/opengl/materialparametergathererjob/materialparametergathererjob.pro new file mode 100644 index 000000000..106e7a263 --- /dev/null +++ b/tests/auto/render/opengl/materialparametergathererjob/materialparametergathererjob.pro @@ -0,0 +1,14 @@ +TEMPLATE = app + +TARGET = tst_materialparametergathererjob + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_materialparametergathererjob.cpp + +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp b/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp new file mode 100644 index 000000000..e6b78c47b --- /dev/null +++ b/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp @@ -0,0 +1,801 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class TestAspect : public Qt3DRender::QRenderAspect +{ +public: + TestAspect(Qt3DCore::QNode *root) + : Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) + , m_jobManager(new Qt3DCore::QAspectJobManager()) + { + Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); + QRenderAspect::onRegistered(); + + QVector nodes; + Qt3DCore::QNodeVisitor v; + v.traverse(root, [&nodes](Qt3DCore::QNode *node) { + Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); + d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); + d->m_hasBackendNode = true; + nodes << node; + }); + + for (const auto node: nodes) + d_func()->createBackendNode({ + node->id(), + Qt3DCore::QNodePrivate::get(node)->m_typeInfo, + Qt3DCore::NodeTreeChange::Added, + node + }); + + const auto handles = nodeManagers()->techniqueManager()->activeHandles(); + for (const auto &handle: handles) { + Render::Technique *technique = nodeManagers()->techniqueManager()->data(handle); + technique->setCompatibleWithRenderer(true); + } + } + + ~TestAspect() + { + QRenderAspect::onUnregistered(); + } + + Qt3DRender::Render::NodeManagers *nodeManagers() const + { + return d_func()->m_renderer->nodeManagers(); + } + + void initializeRenderer() + { + d_func()->m_renderer->initialize(); + } + + Render::MaterialParameterGathererJobPtr materialGathererJob() const + { + Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); + job->setNodeManagers(nodeManagers()); + return job; + } + + void onRegistered() { QRenderAspect::onRegistered(); } + void onUnregistered() { QRenderAspect::onUnregistered(); } + +private: + QScopedPointer m_jobManager; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +namespace { + +class TestMaterial : public Qt3DRender::QMaterial +{ + Q_OBJECT +public: + explicit TestMaterial(Qt3DCore::QNode *parent = nullptr) + : Qt3DRender::QMaterial(parent) + , m_effect(new Qt3DRender::QEffect()) + , m_gl3Technique(new Qt3DRender::QTechnique()) + , m_gl2Technique(new Qt3DRender::QTechnique()) + , m_es2Technique(new Qt3DRender::QTechnique()) + , m_gl3Pass(new Qt3DRender::QRenderPass()) + , m_gl2Pass(new Qt3DRender::QRenderPass()) + , m_es2Pass(new Qt3DRender::QRenderPass()) + , m_gl3Program(new Qt3DRender::QShaderProgram()) + , m_gl2es2Program(new Qt3DRender::QShaderProgram()) + { + m_gl3Pass->setShaderProgram(m_gl3Program); + m_gl2Pass->setShaderProgram(m_gl2es2Program); + m_es2Pass->setShaderProgram(m_gl2es2Program); + + m_gl3Technique->addRenderPass(m_gl3Pass); + m_gl2Technique->addRenderPass(m_gl2Pass); + m_es2Technique->addRenderPass(m_es2Pass); + + m_effect->addTechnique(m_gl3Technique); + m_effect->addTechnique(m_gl2Technique); + m_effect->addTechnique(m_es2Technique); + + setEffect(m_effect); + } + + Qt3DRender::QTechnique *gl3Technique() const { return m_gl3Technique; } + Qt3DRender::QTechnique *gl2Technique() const { return m_gl2Technique; } + Qt3DRender::QTechnique *es2Technique() const { return m_es2Technique; } + + Qt3DRender::QRenderPass *gl3Pass() const { return m_gl3Pass; } + Qt3DRender::QRenderPass *gl2Pass() const { return m_gl2Pass; } + Qt3DRender::QRenderPass *es2Pass() const { return m_es2Pass; } + + Qt3DRender::QShaderProgram *gl3Shader() const { return m_gl3Program; } + Qt3DRender::QShaderProgram *gl2shader() const { return m_gl2es2Program; } + Qt3DRender::QShaderProgram *es2Shader() const { return m_gl2es2Program; } + +private: + Qt3DRender::QEffect *m_effect; + Qt3DRender::QTechnique *m_gl3Technique; + Qt3DRender::QTechnique *m_gl2Technique; + Qt3DRender::QTechnique *m_es2Technique; + Qt3DRender::QRenderPass *m_gl3Pass; + Qt3DRender::QRenderPass *m_gl2Pass; + Qt3DRender::QRenderPass *m_es2Pass; + Qt3DRender::QShaderProgram *m_gl3Program; + Qt3DRender::QShaderProgram *m_gl2es2Program; +}; + +Qt3DRender::QViewport *viewportFrameGraph() +{ + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + return viewport; +} + +Qt3DRender::QTechniqueFilter *techniqueFilterFrameGraph() +{ + Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(); + return techniqueFilter; +} + +Qt3DRender::QRenderPassFilter *renderPassFilter() +{ + Qt3DRender::QRenderPassFilter *passFilter = new Qt3DRender::QRenderPassFilter(); + return passFilter; +} + +Qt3DCore::QEntity *buildScene(Qt3DRender::QFrameGraphNode *frameGraph, Qt3DRender::QMaterial *material = nullptr) +{ + Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); + + // FrameGraph + Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); + renderSettings->setActiveFrameGraph(frameGraph); + root->addComponent(renderSettings); + + // Scene + for (int i = 0; i < 10; i++) { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + if (material != nullptr) + e->addComponent(material); + e->setParent(root); + } + + return root; +} + +} // anonymous + +class tst_MaterialParameterGatherer : public QObject +{ + Q_OBJECT +private Q_SLOTS: + + void checkRunNoHandlesNoTechniqueFilterNoPassFilter() + { + // GIVEN + Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph()); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 0); + + // WHEN + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); + } + + void checkRunSelectAllNoTechniqueFilterNoPassFilter() + { + // GIVEN + TestMaterial material; + Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + } + + void checkRunDisabledMaterial() + { + // GIVEN + TestMaterial material; + material.setEnabled(false); + Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); + } + + void checkRunSelectAllTechniqueFilterWithNoFilterNoPassFilter() + { + // GIVEN + Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); + + TestMaterial material; + + Qt3DRender::QFilterKey techniqueFilterKey; + techniqueFilterKey.setName(QStringLiteral("renderingStyle")); + techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); + + material.gl2Technique()->addFilterKey(&techniqueFilterKey); + material.gl3Technique()->addFilterKey(&techniqueFilterKey); + material.es2Technique()->addFilterKey(&techniqueFilterKey); + + Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); + QVERIFY(backendTechniqueFilter != nullptr); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + } + + void checkRunSelectAllTechniqueFilterWithIncompatibleFilterNoPassFilter() + { + // GIVEN + Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); + TestMaterial material; + + Qt3DRender::QFilterKey techniqueFilterFilterKey; + techniqueFilterFilterKey.setName(QStringLiteral("renderingStyle")); + techniqueFilterFilterKey.setValue(QVariant(QStringLiteral("forward"))); + + Qt3DRender::QFilterKey techniqueFilterKey; + techniqueFilterKey.setName(QStringLiteral("renderingStyle")); + techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); + + frameGraphFilter->addMatch(&techniqueFilterFilterKey); + + material.gl2Technique()->addFilterKey(&techniqueFilterKey); + material.gl3Technique()->addFilterKey(&techniqueFilterKey); + material.es2Technique()->addFilterKey(&techniqueFilterKey); + + Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); + QVERIFY(backendTechniqueFilter != nullptr); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); + } + + void checkRunSelectAllTechniqueFilterWithCompatibleFilterNoPassFilter() + { + // GIVEN + Qt3DRender::QTechniqueFilter *frameGraphFilter = techniqueFilterFrameGraph(); + TestMaterial material; + + Qt3DRender::QFilterKey techniqueFilterKey; + techniqueFilterKey.setName(QStringLiteral("renderingStyle")); + techniqueFilterKey.setValue(QVariant(QStringLiteral("backward"))); + + frameGraphFilter->addMatch(&techniqueFilterKey); + + material.gl2Technique()->addFilterKey(&techniqueFilterKey); + material.gl3Technique()->addFilterKey(&techniqueFilterKey); + material.es2Technique()->addFilterKey(&techniqueFilterKey); + + Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); + QVERIFY(backendTechniqueFilter != nullptr); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + } + + void checkRunSelectAllNoTechniqueFilterPassFilterWithNoFilter() + { + // GIVEN + Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); + TestMaterial material; + + Qt3DRender::QFilterKey passFilterKey; + passFilterKey.setName(QStringLiteral("renderingStyle")); + passFilterKey.setValue(QVariant(QStringLiteral("backward"))); + + material.gl3Pass()->addFilterKey(&passFilterKey); + material.gl2Pass()->addFilterKey(&passFilterKey); + material.es2Pass()->addFilterKey(&passFilterKey); + + Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); + QVERIFY(backendPassFilter != nullptr); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendPassFilter); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + } + + void checkRunSelectAllNoTechniqueFilterPassFilterWithIncompatibleFilter() + { + // GIVEN + Qt3DRender::QRenderPassFilter *frameGraphFilter = renderPassFilter(); + TestMaterial material; + + Qt3DRender::QFilterKey passFilterFilterKey; + passFilterFilterKey.setName(QStringLiteral("renderingStyle")); + passFilterFilterKey.setValue(QVariant(QStringLiteral("forward"))); + + Qt3DRender::QFilterKey passFilterKey; + passFilterKey.setName(QStringLiteral("renderingStyle")); + passFilterKey.setValue(QVariant(QStringLiteral("backward"))); + + frameGraphFilter->addMatch(&passFilterFilterKey); + + material.gl3Pass()->addFilterKey(&passFilterKey); + material.gl2Pass()->addFilterKey(&passFilterKey); + material.es2Pass()->addFilterKey(&passFilterKey); + + Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + + testAspect.initializeRenderer(); + + // THEN + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::RenderPassFilter *backendPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(frameGraphFilter->id())); + QVERIFY(backendPassFilter != nullptr); + + // WHEN + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendPassFilter); + gatherer->run(); + + // THEN + QCOMPARE(gatherer->materialToPassAndParameter().size(), 0); + } + + void checkParameterPriorityGathering() + { + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + techniqueFilterFG->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::red)))); + + auto renderPassParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); + + renderPassFG->addParameter(renderPassParameter); + material.addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::green)))); + material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); + + auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); + + material.gl3Technique()->addParameter(techniqueParam); + material.gl2Technique()->addParameter(techniqueParam); + material.es2Technique()->addParameter(techniqueParam); + + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> RenderPassFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(renderPassParameter->id())); + } + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + auto techniqueFilterParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); + techniqueFilterFG->addParameter(techniqueFilterParameter); + + material.addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::green)))); + material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); + + auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); + + material.gl3Technique()->addParameter(techniqueParam); + material.gl2Technique()->addParameter(techniqueParam); + material.es2Technique()->addParameter(techniqueParam); + + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> TechniqueFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueFilterParameter->id())); + } + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + auto materialParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); + + material.addParameter(materialParameter); + material.effect()->addParameter(new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::blue)))); + + auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); + + material.gl3Technique()->addParameter(techniqueParam); + material.gl2Technique()->addParameter(techniqueParam); + material.es2Technique()->addParameter(techniqueParam); + + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> TechniqueFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(materialParameter->id())); + } + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + auto effectParameter = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::cyan))); + + material.effect()->addParameter(effectParameter); + + auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); + + material.gl3Technique()->addParameter(techniqueParam); + material.gl2Technique()->addParameter(techniqueParam); + material.es2Technique()->addParameter(techniqueParam); + + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> TechniqueFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(effectParameter->id())); + } + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + auto techniqueParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::white))); + + material.gl3Technique()->addParameter(techniqueParam); + material.gl2Technique()->addParameter(techniqueParam); + material.es2Technique()->addParameter(techniqueParam); + + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> TechniqueFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueParam->id())); + } + { + // GIVEN + Qt3DRender::QTechniqueFilter *techniqueFilterFG = techniqueFilterFrameGraph(); + Qt3DRender::QRenderPassFilter *renderPassFG = renderPassFilter(); + + renderPassFG->setParent(techniqueFilterFG); + + TestMaterial material; + + Qt3DCore::QEntity *sceneRoot = buildScene(techniqueFilterFG, &material); + + // WHEN + auto passParam = new Qt3DRender::QParameter(QStringLiteral("color"), QVariant(QColor(Qt::gray))); + + material.gl3Pass()->addParameter(passParam); + material.gl2Pass()->addParameter(passParam); + material.es2Pass()->addParameter(passParam); + + Qt3DRender::TestAspect testAspect(sceneRoot); + Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + testAspect.initializeRenderer(); + + QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); + Qt3DRender::Render::TechniqueFilter *backendTechniqueFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(techniqueFilterFG->id())); + Qt3DRender::Render::RenderPassFilter *backendRenderPassFilter = static_cast(testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFG->id())); + QVERIFY(backendTechniqueFilter != nullptr); + QVERIFY(backendRenderPassFilter != nullptr); + + gatherer->setHandles(testAspect.nodeManagers()->materialManager()->activeHandles()); + gatherer->setRenderPassFilter(backendRenderPassFilter); + gatherer->setTechniqueFilter(backendTechniqueFilter); + gatherer->run(); + + // THEN -> TechniqueFilter wins + QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); + + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + QCOMPARE(passParameterData.size(), 1); + + const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + + QCOMPARE(data.parameterInfo.size(), 1); + QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(passParam->id())); + } + } +}; + +QTEST_MAIN(tst_MaterialParameterGatherer) + +#include "tst_materialparametergathererjob.moc" diff --git a/tests/auto/render/opengl/opengl.pro b/tests/auto/render/opengl/opengl.pro new file mode 100644 index 000000000..5299ebd36 --- /dev/null +++ b/tests/auto/render/opengl/opengl.pro @@ -0,0 +1,19 @@ +TEMPLATE = subdirs + +SUBDIRS += \ + filtercompatibletechniquejob \ + graphicshelpergl3_3 \ + graphicshelpergl3_2 \ + graphicshelpergl2 \ + glshadermanager \ + materialparametergathererjob \ + textures \ + renderer \ + renderviewutils \ + renderviews \ + renderqueue \ + renderviewbuilder \ + qgraphicsutils \ + computecommand + +!macos: SUBDIRS += graphicshelpergl4 diff --git a/tests/auto/render/opengl/opengl_render_plugin.pri b/tests/auto/render/opengl/opengl_render_plugin.pri new file mode 100644 index 000000000..50fade878 --- /dev/null +++ b/tests/auto/render/opengl/opengl_render_plugin.pri @@ -0,0 +1,18 @@ +# Found no way of having the test runner include the correct +# library path as runtime + +#PLUGIN_SRC_PATH = $$PWD/../../../../src/plugins/renderers/opengl + +#INCLUDEPATH += \ +# $$PLUGIN_SRC_PATH/graphicshelpers \ +# $$PLUGIN_SRC_PATH/io \ +# $$PLUGIN_SRC_PATH/jobs \ +# $$PLUGIN_SRC_PATH/managers \ +# $$PLUGIN_SRC_PATH/renderer \ +# $$PLUGIN_SRC_PATH/renderstates \ +# $$PLUGIN_SRC_PATH/textures + +#LIBS += -L$$[QT_INSTALL_PLUGINS]/renderers/ -lopenglrenderer + +# Instead we link against the sources directly +include(../../../../src/plugins/renderers/opengl/opengl.pri) diff --git a/tests/auto/render/opengl/qgraphicsutils/qgraphicsutils.pro b/tests/auto/render/opengl/qgraphicsutils/qgraphicsutils.pro new file mode 100644 index 000000000..8c936c527 --- /dev/null +++ b/tests/auto/render/opengl/qgraphicsutils/qgraphicsutils.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qgraphicsutils + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_qgraphicsutils.cpp + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp b/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp new file mode 100644 index 000000000..2e0dd0f96 --- /dev/null +++ b/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include + +class tst_QGraphicsUtils : public QObject +{ + Q_OBJECT +private slots: + void fillScalarInDataArray(); + void fillArray(); + void fillScalarWithOffsets(); + void fillMatrix4x4(); + void fillMatrix3x4(); + void fillMatrix4x3(); + void fillMatrixArray(); +}; + +void tst_QGraphicsUtils::fillScalarInDataArray() +{ + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 1; + description.m_offset = 0; + description.m_arrayStride = 10; + + QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); + const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(testVector, 1, 4); + + for (int i = 0; i < 4; i++) { + if (i == 0) + QVERIFY(vectorData[i] == testVector.x()); + else if (i == 1) + QVERIFY(vectorData[i] == testVector.y()); + else if (i == 2) + QVERIFY(vectorData[i] == testVector.z()); + else if (i == 3) + QVERIFY(vectorData[i] == testVector.w()); + } + + QByteArray data(description.m_size * 4 * sizeof(GLfloat), 0); + char *innerData = data.data(); + + // Checked that we are not overflowing + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 2); + for (int i = 0; i < 4; ++i) { + if (i < 2) + QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); + else + QVERIFY(((GLfloat*)innerData)[i] == 0.0f); + } + + // Check that all values are copied + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + for (int i = 0; i < 4; ++i) + QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); + + // check that offsetting works + description.m_offset = 16; + data = QByteArray(description.m_size * 8 * sizeof(GLfloat), 0); + innerData = data.data(); + + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + for (int i = 0; i < 8; ++i) { + if (i < 4) + QVERIFY(((GLfloat*)innerData)[i] == 0.0f); + else + QVERIFY(vectorData[i - 4] == ((GLfloat*)innerData)[i]); + } +} + +void tst_QGraphicsUtils::fillArray() +{ + QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); + QVector4D testVector2(3.0f, 5.0f, 0.0f, 7.0f); + QVector4D testVector3(4.0f, 5.0f, 4.0f, 2.0f); + + QVariantList variantList = QVariantList() << testVector << testVector2 << testVector3; + const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant(variantList), 3, 4); + + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 3; + description.m_offset = 16; + description.m_arrayStride = 16; + + QByteArray data(description.m_size * (4 + description.m_arrayStride) * sizeof(GLfloat) + description.m_offset, 0); + char *innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + + int offset = description.m_offset / sizeof(GLfloat); + int stride = description.m_arrayStride / sizeof(GLfloat); + + GLfloat *innerDataFloat = (GLfloat*)innerData; + + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 4; ++j) { + int idx = i * 4 + j; + QVERIFY(innerDataFloat[offset + j] == vectorData[idx]); + } + offset += stride; + } +} + +void tst_QGraphicsUtils::fillScalarWithOffsets() +{ + // Simulates Uniform Block + + // uniform Block { + // vec3 position; // Offset 0 - 12 bytes + // vec3 direction; // Offset 16 - 12 bytes + // vec4 color; // Offset 32 - 16 bytes + // float intensity; // Offset 48 - bytes + // } // total size 64 bytes + + QVector3D position(8.0f, 8.0f, 3.0f); + QVector3D direction(3.0f, 5.0f, 2.0f); + QVector4D color(4.0f, 5.0f, 4.0f, 1.0f); + float intensity = 1.0f; + + Qt3DRender::Render::ShaderUniform posUniform; + posUniform.m_size = 1; + posUniform.m_arrayStride = 0; + posUniform.m_matrixStride = 0; + posUniform.m_offset = 0; + + Qt3DRender::Render::ShaderUniform dirUniform; + dirUniform.m_size = 1; + dirUniform.m_arrayStride = 0; + dirUniform.m_matrixStride = 0; + dirUniform.m_offset = 16; + + Qt3DRender::Render::ShaderUniform colUniform; + colUniform.m_size = 1; + colUniform.m_arrayStride = 0; + colUniform.m_matrixStride = 0; + colUniform.m_offset = 32; + + Qt3DRender::Render::ShaderUniform intUniform; + intUniform.m_size = 1; + intUniform.m_arrayStride = 0; + intUniform.m_matrixStride = 0; + intUniform.m_offset = 48; + + QVector data(16); + void *innerData = data.data(); + + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(position, 1, 3), + posUniform, 3); + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(direction, 1, 3), + dirUniform, 3); + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(color, 1, 4), + colUniform, 4); + Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(intensity, 1, 1), + intUniform, 1); + + GLfloat *floatData = (GLfloat*)innerData; + + // Check first 16 bytes - position + QVERIFY(floatData[0] == position.x()); + QVERIFY(floatData[1] == position.y()); + QVERIFY(floatData[2] == position.z()); + QVERIFY(floatData[3] == 0.0f); + // Check 16 - 32 bytes - direction + QVERIFY(floatData[4] == direction.x()); + QVERIFY(floatData[5] == direction.y()); + QVERIFY(floatData[6] == direction.z()); + QVERIFY(floatData[7] == 0.0f); + // Check 32 - 48 bytes - color + QVERIFY(floatData[8] == color.x()); + QVERIFY(floatData[9] == color.y()); + QVERIFY(floatData[10] == color.z()); + QVERIFY(floatData[11] == color.w()); + // Check 48 - 64 bytes - intensity + QVERIFY(floatData[12] == intensity); + QVERIFY(floatData[13] == 0.0f); + QVERIFY(floatData[14] == 0.0f); + QVERIFY(floatData[15] == 0.0f); +} + +void tst_QGraphicsUtils::fillMatrix4x4() +{ + // row major + QMatrix4x4 mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f); + + // column major + const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(mat, 1, 16); + + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 1; + description.m_offset = 0; + description.m_arrayStride = 0; + description.m_matrixStride = 16; + + + QByteArray data(description.m_size * 16 * sizeof(GLfloat), 0); + char *innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + // Check for no offset/no stride + for (int i = 0; i < 16; ++i) + QVERIFY((((GLfloat *)innerData)[i]) == matData[i]); + + description.m_offset = 12; + data = QByteArray((description.m_size * 16 + description.m_offset) * sizeof(GLfloat), 0); + innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + // Check with 12 offset/no stride + for (int i = 0; i < 16; ++i) + QVERIFY((((GLfloat *)innerData)[3 + i]) == matData[i]); + + description.m_matrixStride = 16; + data = QByteArray((description.m_size * 16 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); + innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + // Check with 10 offset/ 16 stride + int offset = description.m_offset / sizeof(GLfloat); + int matrixStride = description.m_matrixStride / sizeof(GLfloat); + + for (int col = 0; col < 4; ++col) { + for (int row = 0; row < 4; ++row) + QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); + offset += matrixStride; + } +} + +void tst_QGraphicsUtils::fillMatrix3x4() +{ + QMatrix3x4 mat; + + mat.fill(6.0f); + const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); + + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 1; + description.m_offset = 16; + description.m_arrayStride = 0; + description.m_matrixStride = 12; + + QByteArray data((description.m_size * 12 + 3 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); + char *innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 3, 4); + // Check with 16 offset/ 12 stride + int offset = description.m_offset / sizeof(GLfloat); + int matrixStride = description.m_matrixStride / sizeof(GLfloat); + + for (int col = 0; col < 3; ++col) { + for (int row = 0; row < 4; ++row) + QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); + offset += matrixStride; + } +} + +void tst_QGraphicsUtils::fillMatrix4x3() +{ + QMatrix4x3 mat; + + mat.fill(6.0f); + const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); + + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 1; + description.m_offset = 16; + description.m_arrayStride = 0; + description.m_matrixStride = 16; + + QByteArray data((description.m_size * 12 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); + char *innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); + // Check with 16 offset/ 16 stride + int offset = description.m_offset / sizeof(GLfloat); + int matrixStride = description.m_matrixStride / sizeof(GLfloat); + + for (int col = 0; col < 4; ++col) { + for (int row = 0; row < 3; ++row) + QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 3 + row]); + offset += matrixStride; + } +} + +void tst_QGraphicsUtils::fillMatrixArray() +{ + QMatrix4x3 mat1; + QMatrix4x3 mat2; + QMatrix4x3 mat3; + mat1.fill(6.0f); + mat2.fill(2.0f); + mat3.fill(7.0f); + + QVariantList matrices = QVariantList() << QVariant::fromValue(mat1) << QVariant::fromValue(mat2) << QVariant::fromValue(mat3); + + const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(matrices), 3, 12); + + Qt3DRender::Render::ShaderUniform description; + + description.m_size = 3; + description.m_offset = 12; + description.m_arrayStride = 4; + description.m_matrixStride = 16; + + QByteArray data((description.m_size * (12 + 4 * description.m_matrixStride + description.m_arrayStride) + description.m_offset) * sizeof(GLfloat), 0); + char *innerData = data.data(); + Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); + // Check with 12 offset/ 4 array stride / 16 matrix stride + int offset = description.m_offset / sizeof(GLfloat); + int matrixStride = description.m_matrixStride / sizeof(GLfloat); + int arrayStride = description.m_arrayStride / sizeof(GLfloat); + + for (int i = 0; i < 3; ++i) { + for (int col = 0; col < 4; ++col) { + for (int row = 0; row < 3; ++row) { + int idx = i * 4 * 3 + col * 3 + row; + QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[idx]); + } + offset += matrixStride; + } + offset += arrayStride; + } +} + +QTEST_APPLESS_MAIN(tst_QGraphicsUtils) + +#include "tst_qgraphicsutils.moc" diff --git a/tests/auto/render/opengl/renderer/renderer.pro b/tests/auto/render/opengl/renderer/renderer.pro new file mode 100644 index 000000000..d481c7b9e --- /dev/null +++ b/tests/auto/render/opengl/renderer/renderer.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_renderer + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderer.cpp + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/renderer/tst_renderer.cpp b/tests/auto/render/opengl/renderer/tst_renderer.cpp new file mode 100644 index 000000000..6aed6ed5f --- /dev/null +++ b/tests/auto/render/opengl/renderer/tst_renderer.cpp @@ -0,0 +1,348 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class tst_Renderer : public QObject +{ + Q_OBJECT +public : + tst_Renderer() {} + ~tst_Renderer() {} + +private Q_SLOTS: + + void checkPreRenderBinJobs() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); + Qt3DRender::Render::RenderSettings settings; + // owned by FG manager + Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); + const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); + + nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); + settings.setActiveFrameGraphId(fgRootId); + + renderer.setNodeManagers(&nodeManagers); + renderer.setSettings(&settings); + renderer.setOffscreenSurfaceHelper(&offscreenHelper); + renderer.initialize(); + + // Ensure invoke calls are performed + QCoreApplication::processEvents(); + + // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) + QVector jobs = renderer.preRenderingJobs(); + + // THEN + QCOMPARE(jobs.size(), + 1 + // PickBoundingVolumeJob + 1); // RayCastingJob + + // WHEN + renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); + jobs = renderer.preRenderingJobs(); + + // THEN + QCOMPARE(jobs.size(), + 1 + // PickBoundingVolumeJob + 1 + // RayCastingJob + 1); // SendBufferCaptureJob + // Note: pending render buffer captures are only cleared when the job is run + + // WHEN + renderer.m_updatedSetFences.push_back({Qt3DCore::QNodeId(), nullptr}); + jobs = renderer.preRenderingJobs(); + + // THEN + QCOMPARE(jobs.size(), + 1 + // PickBoundingVolumeJob + 1 + // RayCastingJob + 1 + // SendBufferCaptureJob + 1); // SendSetFenceHandlesJob + // Note: pending set fence handles are only cleared when the job is run + + // Properly shutdown command thread + renderer.shutdown(); + } + + void checkRenderBinJobs() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::RenderQueue *renderQueue = renderer.renderQueue(); + Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); + Qt3DRender::Render::RenderSettings settings; + // owned by FG manager + Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); + const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); + + nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); + settings.setActiveFrameGraphId(fgRootId); + + renderer.setNodeManagers(&nodeManagers); + renderer.setSettings(&settings); + renderer.setOffscreenSurfaceHelper(&offscreenHelper); + renderer.initialize(); + + // Ensure invoke calls are performed + QCoreApplication::processEvents(); + + // NOTE: FilterCompatibleTechniqueJob and ShaderGathererJob cannot run because the context + // is not initialized in this test + + const int renderViewBuilderMaterialCacheJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + // syncMaterialGathererJob + // n * materialGathererJob + const int layerCacheJobCount = 2; + // filterEntityByLayerJob, + // syncFilterEntityByLayerJob + + const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + + const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + // RenderViewBuilder renderViewJob, + // syncRenderViewInitializationJob, + // syncFrustumCullingJob, + // filterProximityJob, + // setClearDrawBufferIndexJob, + // frustumCullingJob, + // syncRenderCommandUpdateJob, + // syncRenderViewCommandPostUpdateJob + // n * (RenderViewCommandBuildJobs) + + // WHEN + QVector jobs = renderer.renderBinJobs(); + + // THEN -> AllDirty + // (Renderer is not initialized so FilterCompatibleTechniqueJob + // and ShaderGathererJob are not added here) + QCOMPARE(jobs.size(), + 1 + // EntityEnabledDirty + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // ExpandBoundingVolumeJob + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // BufferGathererJob + 1 + // TexturesGathererJob + 1 + // UpdateEntityLayersJob + 1 + // LightGathererJob + 1 + // CacheLightJob + 1 + // RenderableEntityFilterJob + 1 + // CacheRenderableEntitiesJob + 1 + // ComputableEntityFilterJob + 1 + // CacheComputableEntitiesJob + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + layerCacheJobCount + + renderViewBuilderMaterialCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache) + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + renderViewBuilderMaterialCacheJobCount + + layerCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache) + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); + renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {}; + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + renderViewBuilderMaterialCacheJobCount + + layerCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // EntityEnabledDirty + singleRenderViewJobCount + + layerCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // WorldTransformJob + 1 + // UpdateWorldBoundingVolume + 1 + // UpdateShaderDataTransform + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // ExpandBoundingVolumeJob + singleRenderViewJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::MaterialDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + singleRenderViewJobCount + + singleRenderViewCommandRebuildJobCount + + renderViewBuilderMaterialCacheJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // ExpandBoundingVolumeJob + 1 + // RenderableEntityFilterPtr + 1 + // SyncRenderableEntities + singleRenderViewCommandRebuildJobCount + + singleRenderViewJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // updateSkinningPaletteJob + 1 + // SyncLoadingJobs + 1 + // CalculateBoundingVolumeJob + 1 + // UpdateMeshTriangleListJob + 1 + // BufferGathererJob + singleRenderViewJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // WHEN + renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); + jobs = renderer.renderBinJobs(); + + // THEN (level + QCOMPARE(jobs.size(), + 1 + // updateLevelOfDetailJob + 1 + // cleanupJob + 1 + // VAOGatherer + 1 + // TexturesGathererJob + 1 + // updateSkinningPaletteJob + 1 + // SyncTexturesGathererJob + singleRenderViewJobCount); + + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + renderQueue->reset(); + + // Properly shutdown command thread + renderer.shutdown(); + } +}; + +QTEST_MAIN(tst_Renderer) + +#include "tst_renderer.moc" diff --git a/tests/auto/render/opengl/renderqueue/renderqueue.pro b/tests/auto/render/opengl/renderqueue/renderqueue.pro new file mode 100644 index 000000000..19106ba92 --- /dev/null +++ b/tests/auto/render/opengl/renderqueue/renderqueue.pro @@ -0,0 +1,14 @@ +TEMPLATE = app + +TARGET = tst_renderqueue + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderqueue.cpp + +include(../../../core/common/common.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp b/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp new file mode 100644 index 000000000..2be089495 --- /dev/null +++ b/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include + +class tst_RenderQueue : public QObject +{ + Q_OBJECT +public : + tst_RenderQueue() {} + ~tst_RenderQueue() {} + +private Q_SLOTS: + void setRenderViewCount(); + void circleQueues(); + void checkOrder(); + void checkTimeToSubmit(); + void concurrentQueueAccess(); + void resetQueue(); +}; + + +void tst_RenderQueue::setRenderViewCount() +{ + // GIVEN + Qt3DRender::Render::RenderQueue renderQueue; + + // THEN + QCOMPARE(renderQueue.wasReset(), true); + + // WHEN + renderQueue.setTargetRenderViewCount(7); + + // THEN + QCOMPARE(renderQueue.wasReset(), false); + QVERIFY(renderQueue.targetRenderViewCount() == 7); + QVERIFY(renderQueue.currentRenderViewCount()== 0); +} + +void tst_RenderQueue::circleQueues() +{ + // GIVEN + Qt3DRender::Render::RenderQueue renderQueue; + renderQueue.setTargetRenderViewCount(7); + + // WHEN + for (int j = 0; j < 10; j++) { + + // WHEN + renderQueue.reset(); + renderQueue.setTargetRenderViewCount(7); + + // THEN + QVERIFY(!renderQueue.isFrameQueueComplete()); + QCOMPARE(renderQueue.currentRenderViewCount(), 0); + + // WHEN + QList renderViews; + for (int i = 0; i < 7; i++) { + renderViews << new Qt3DRender::Render::RenderView(); + renderQueue.queueRenderView(renderViews.at(i), i); + } + + // THEN + QVERIFY(renderQueue.isFrameQueueComplete()); + } +} + +void tst_RenderQueue::checkOrder() +{ + // GIVEN + Qt3DRender::Render::RenderQueue renderQueue; + renderQueue.setTargetRenderViewCount(7); + QVector renderViews(7); + + // WHEN + for (int i = 0; i < 7; ++i) { + int processingOrder = (i % 2 == 0) ? (6 - i) : i; + renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); + renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); + } + + // THEN + QVector frame = renderQueue.nextFrameQueue(); + for (int i = 0; i < 7; ++i) { + QVERIFY(frame[i] == renderViews[i]); + } +} + +void tst_RenderQueue::checkTimeToSubmit() +{ + // GIVEN + Qt3DRender::Render::RenderQueue renderQueue; + renderQueue.setTargetRenderViewCount(7); + QVector renderViews(7); + + // WHEN + for (int i = 0; i < 7; i++) { + int processingOrder = (i % 2 == 0) ? (6 - i) : i; + renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); + renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); + + // THEN + if (i < 6) + QVERIFY(!renderQueue.isFrameQueueComplete()); + else + QVERIFY(renderQueue.isFrameQueueComplete()); + } +} + +class SimpleWorker : public QThread +{ + Q_OBJECT +public: + QSemaphore m_waitSubmit; + QSemaphore m_waitQueue; + Qt3DRender::Render::RenderQueue *m_renderQueues; + +public Q_SLOTS: + + void run() final // In Thread + { + for (int i = 0; i < 5; i++) { + m_waitQueue.acquire(); + + QVERIFY(m_renderQueues->currentRenderViewCount() == 0); + QVERIFY(!m_renderQueues->isFrameQueueComplete()); + + for (int j = 0; j < 7; ++j) { + // THEN + QCOMPARE(m_renderQueues->currentRenderViewCount(), j); + // WHEN + m_renderQueues->queueRenderView(new Qt3DRender::Render::RenderView(), j); + // THEN + QVERIFY(m_renderQueues->targetRenderViewCount() == 7); + QCOMPARE(m_renderQueues->currentRenderViewCount(), j + 1); + QVERIFY(m_renderQueues->isFrameQueueComplete() == (j == 6)); + QThread::msleep(20); // Simulates business + } + + QVERIFY(m_renderQueues->isFrameQueueComplete()); + m_waitSubmit.release(); + } + } +}; + + +void tst_RenderQueue::concurrentQueueAccess() +{ + // GIVEN + Qt3DRender::Render::RenderQueue *renderQueue = new Qt3DRender::Render::RenderQueue; + + SimpleWorker *jobsThread = new SimpleWorker(); + renderQueue->setTargetRenderViewCount(7); + jobsThread->m_renderQueues = renderQueue; + + // THEN + QVERIFY(jobsThread->m_renderQueues->targetRenderViewCount() == renderQueue->targetRenderViewCount()); + QVERIFY(jobsThread->m_renderQueues->currentRenderViewCount() == renderQueue->currentRenderViewCount()); + + // Start thread + jobsThread->start(); + + jobsThread->m_waitQueue.release(); + + for (int i = 0; i < 5; ++i) { + jobsThread->m_waitSubmit.acquire(); + + // WHEN unlocked + // THEN + QVERIFY (renderQueue->isFrameQueueComplete()); + QCOMPARE(renderQueue->nextFrameQueue().size(), renderQueue->targetRenderViewCount()); + + // reset queue for next frame + renderQueue->reset(); + renderQueue->setTargetRenderViewCount(7); + jobsThread->m_waitQueue.release(); + } + jobsThread->wait(); +} + +void tst_RenderQueue::resetQueue() +{ + // GIVEN + Qt3DRender::Render::RenderQueue renderQueue; + + for (int j = 0; j < 5; j++) { + // WHEN + renderQueue.setTargetRenderViewCount(5); + // THEN + QCOMPARE(renderQueue.wasReset(), false); + QVERIFY(renderQueue.currentRenderViewCount() == 0); + + // WHEN + QVector renderViews(5); + for (int i = 0; i < 5; ++i) { + renderQueue.queueRenderView(renderViews.at(i), i); + } + // THEN + QCOMPARE(renderQueue.currentRenderViewCount(), 5); + QVERIFY(renderQueue.isFrameQueueComplete()); + + // WHEN + renderQueue.reset(); + QCOMPARE(renderQueue.wasReset(), true); + // THEN + QVERIFY(renderQueue.currentRenderViewCount() == 0); + } +} + +QTEST_APPLESS_MAIN(tst_RenderQueue) + +#include "tst_renderqueue.moc" diff --git a/tests/auto/render/opengl/renderviewbuilder/renderviewbuilder.pro b/tests/auto/render/opengl/renderviewbuilder/renderviewbuilder.pro new file mode 100644 index 000000000..b7b8f5b81 --- /dev/null +++ b/tests/auto/render/opengl/renderviewbuilder/renderviewbuilder.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_renderviewbuilder + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderviewbuilder.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp new file mode 100644 index 000000000..6dc463589 --- /dev/null +++ b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp @@ -0,0 +1,669 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +class TestAspect : public QRenderAspect +{ +public: + TestAspect(Qt3DCore::QNode *root) + : QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) + , m_jobManager(new Qt3DCore::QAspectJobManager()) + { + Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); + QRenderAspect::onRegistered(); + + QVector nodes; + Qt3DCore::QNodeVisitor v; + v.traverse(root, [&nodes](Qt3DCore::QNode *node) { + Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); + d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); + d->m_hasBackendNode = true; + nodes << node; + }); + + for (const auto node: nodes) + d_func()->createBackendNode({ + node->id(), + Qt3DCore::QNodePrivate::get(node)->m_typeInfo, + Qt3DCore::NodeTreeChange::Added, + node + }); + } + + ~TestAspect() + { + QRenderAspect::onUnregistered(); + } + + Qt3DRender::Render::NodeManagers *nodeManagers() const + { + return d_func()->m_renderer->nodeManagers(); + } + + Render::Renderer *renderer() const + { + return static_cast(d_func()->m_renderer); + } + + Render::MaterialParameterGathererJobPtr materialGathererJob() const + { + Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); + job->setNodeManagers(nodeManagers()); + return job; + } + + void onRegistered() { QRenderAspect::onRegistered(); } + void onUnregistered() { QRenderAspect::onUnregistered(); } + +private: + QScopedPointer m_jobManager; +}; + +} // namespace Qt3DRender + +QT_END_NAMESPACE + +namespace { + +Qt3DCore::QEntity *buildSimpleScene(Qt3DRender::QFrameGraphNode *fg) +{ + Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); + + Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); + renderSettings->setActiveFrameGraph(fg); + root->addComponent(renderSettings); + + // Scene + { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DRender::QGeometryRenderer(); + e->addComponent(material); + e->addComponent(geometryRenderer); + e->setParent(root); + } + { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); + Qt3DRender::QComputeCommand *computeCommand = new Qt3DRender::QComputeCommand(); + e->addComponent(material); + e->addComponent(computeCommand); + e->setParent(root); + } + + { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(); + e->addComponent(light); + e->setParent(root); + } + + { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QSpotLight *light = new Qt3DRender::QSpotLight(); + e->addComponent(light); + e->setParent(root); + } + + { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QEnvironmentLight *light = new Qt3DRender::QEnvironmentLight(); + e->addComponent(light); + e->setParent(root); + } + + return root; +} + +Qt3DCore::QEntity *buildEntityFilterTestScene(Qt3DRender::QFrameGraphNode *fg, Qt3DRender::QLayer *layer) +{ + Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); + + Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); + renderSettings->setActiveFrameGraph(fg); + root->addComponent(renderSettings); + + // Scene + for (int i = 0; i < 200; ++i) { + Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); + Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); + Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DRender::QGeometryRenderer(); + e->addComponent(material); + e->addComponent(geometryRenderer); + if (i % 2 == 0) + e->addComponent(layer); + e->setParent(root); + } + + return root; +} + +} // anonymous + + +class tst_RenderViewBuilder : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + + void checkInitialState() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + + // THEN + QCOMPARE(renderViewBuilder.renderViewIndex(), 0); + QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), false); + QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), false); + QVERIFY(!renderViewBuilder.renderViewJob().isNull()); + QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.syncPreFrustumCullingJob().isNull()); + QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); + + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); + QVERIFY(renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), 0); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); + + // WHEN + renderViewBuilder.prepareJobs(); + + // THEN + QVERIFY(!renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); + QVERIFY(!renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } + + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + + // THEN + QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), true); + QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + // mark jobs dirty and recheck + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } + + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + + // THEN + QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), true); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QVERIFY(!renderViewBuilder.syncMaterialGathererJob().isNull()); + + // mark jobs dirty and recheck + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + } + } + + void checkCheckJobDependencies() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.renderViewJob().data()); + + // Step 3 + QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.syncRenderViewPostInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + + QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob())); + + // Step 5 + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); + } + } + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + // Step 1 + QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update + + // Step 2 + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.renderViewJob().data()); + + // Step 3 + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); + + QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); + QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); + + QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); + QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.syncRenderViewPostInitializationJob().data()); + + QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); + QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); + + for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { + QCOMPARE(materialGatherer->dependencies().size(), 3); + QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob())); + QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); + } + + // Step 4 + QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); + QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); + + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); + QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); + + // Step 5 + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); + QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), + renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); + } + + // Step 6 + QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); + for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { + QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); + } + } + } + + void checkRenderViewJobExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + renderViewBuilder.renderViewJob()->run(); + + // THEN + QVERIFY(renderViewBuilder.renderViewJob()->renderView() != nullptr); + } + + void checkLightGatherExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + renderer->lightGathererJob()->run(); + + // THEN + QCOMPARE(renderer->lightGathererJob()->lights().size(), 2); + QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr); + } + + void checkRenderableEntitiesFilteringExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + renderer->renderableEntityFilterJob()->run(); + + // THEN + QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1); + } + + void checkComputableEntitiesFilteringExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + renderer->computableEntityFilterJob()->run(); + + // THEN + QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1); + } + + void checkSyncRenderViewInitializationExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(clearBuffer); + Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(layerFilter); + Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(frustumCulling); + Qt3DRender::QRenderPassFilter *renderPassFilter = new Qt3DRender::QRenderPassFilter(techniqueFilter); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); + + layerFilter->addLayer(layer); + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFilter->id()); + QVERIFY(leafNode != nullptr); + + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } + } + { + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0); + for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() == nullptr); + QVERIFY(materialGatherer->renderPassFilter() == nullptr); + } + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); + QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1); + for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { + QVERIFY(materialGatherer->techniqueFilter() != nullptr); + QVERIFY(materialGatherer->renderPassFilter() != nullptr); + } + } + } + + void checkSyncFrustumCullingExecution() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(clearBuffer); + Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(frustumCulling); + Qt3DRender::QCamera *camera = new Qt3DRender::QCamera(); + cameraSelector->setCamera(camera); + + Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(cameraSelector->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + // THEN + QCOMPARE(renderViewBuilder.frustumCullingJob()->viewProjection(), Matrix4x4()); + + // WHEN + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncPreFrustumCullingJob()->run(); + + // THEN + QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix()); + } + + void checkRemoveEntitiesNotInSubset() + { + // GIVEN + Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); + Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); + Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(clearBuffer); + Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); + layerFilter->addLayer(layer); + Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer)); + Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + + // THEN + Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id()); + QVERIFY(leafNode != nullptr); + + // WHEN + renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); + + Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); + renderViewBuilder.prepareJobs(); + renderViewBuilder.buildJobHierachy(); + + renderer->renderableEntityFilterJob()->run(); + renderer->cacheRenderableEntitiesJob()->run(); + + renderViewBuilder.renderViewJob()->run(); + renderViewBuilder.syncRenderViewPostInitializationJob()->run(); + renderViewBuilder.filterEntityByLayerJob()->run(); + + QVector renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities(); + QVector filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities(); + + // THEN + QCOMPARE(renderableEntity.size(), 200); + QCOMPARE(filteredEntity.size(), 100); + + std::sort(renderableEntity.begin(), renderableEntity.end()); + + // WHEN + renderableEntity = Qt3DRender::Render::RenderViewBuilder::entitiesInSubset(renderableEntity, filteredEntity); + + // THEN + QCOMPARE(renderableEntity.size(), 100); + for (const auto entity : renderableEntity) { + QVERIFY(filteredEntity.contains(entity)); + } + } + +}; + +QTEST_MAIN(tst_RenderViewBuilder) + +#include "tst_renderviewbuilder.moc" diff --git a/tests/auto/render/opengl/renderviews/renderviews.pro b/tests/auto/render/opengl/renderviews/renderviews.pro new file mode 100644 index 000000000..7efbaec14 --- /dev/null +++ b/tests/auto/render/opengl/renderviews/renderviews.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_renderviews + +QT += 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderviews.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp new file mode 100644 index 000000000..d30b8ddca --- /dev/null +++ b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp @@ -0,0 +1,554 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Render { + +namespace { + +void compareShaderParameterPacks(const ShaderParameterPack &t1, + const ShaderParameterPack &t2) +{ + const PackUniformHash hash1 = t1.uniforms(); + const PackUniformHash hash2 = t2.uniforms(); + + QCOMPARE(hash1.keys.size(), hash2.keys.size()); + + for (int i = 0, m = hash1.keys.size(); i < m; ++i) { + const int key = hash1.keys.at(i); + QCOMPARE(hash1.value(key), hash2.value(key)); + } +} + +} // anonymous + +class tst_RenderViews : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + + void checkRenderViewSizeFitsWithAllocator() + { + QSKIP("Allocated Disabled"); + QVERIFY(sizeof(RenderView) <= 192); + QVERIFY(sizeof(RenderView::InnerData) <= 192); + } + + void checkRenderViewInitialState() + { + // GIVEN + RenderView renderView; + + // THEN + QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); + } + + void checkMemoryBarrierInitialization() + { + // GIVEN + RenderView renderView; + + // THEN + QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); + + // WHEN + const QMemoryBarrier::Operations barriers(QMemoryBarrier::BufferUpdate|QMemoryBarrier::ShaderImageAccess); + renderView.setMemoryBarrier(barriers); + + // THEN + QCOMPARE(renderView.memoryBarrier(), barriers); + } + + void checkSetRenderViewConfig() + { + TestRenderer renderer; + { + // GIVEN + const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage); + Qt3DRender::QMemoryBarrier frontendBarrier; + FrameGraphManager frameGraphManager; + MemoryBarrier backendBarrier; + RenderView renderView; + // setRenderViewConfigFromFrameGraphLeafNode assumes node has a manager + backendBarrier.setFrameGraphManager(&frameGraphManager); + backendBarrier.setRenderer(&renderer); + + // WHEN + frontendBarrier.setWaitOperations(barriers); + simulateInitializationSync(&frontendBarrier, &backendBarrier); + + // THEN + QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); + QCOMPARE(backendBarrier.waitOperations(), barriers); + + // WHEN + Qt3DRender::Render::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); + + // THEN + QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); + } + // TO DO: Complete tests for other framegraph node types + } + + void checkRenderCommandBackToFrontSorting() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + QVector rawCommands; + QVector sortTypes; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + sortTypes.push_back(QSortPolicy::BackToFront); + + for (int i = 0; i < 200; ++i) { + RenderCommand c; + c.m_depth = float(i); + rawCommands.push_back(c); + } + + // WHEN + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + for (int j = 1; j < sortedCommands.size(); ++j) + QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth); + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + + void checkRenderCommandMaterialSorting() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + QVector rawCommands; + QVector sortTypes; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + sortTypes.push_back(QSortPolicy::Material); + + GLShader *dnas[5] = { + reinterpret_cast(0x250), + reinterpret_cast(0x500), + reinterpret_cast(0x1000), + reinterpret_cast(0x1500), + reinterpret_cast(0x2000) + }; + + for (int i = 0; i < 20; ++i) { + RenderCommand c; + c.m_glShader = dnas[i % 5]; + rawCommands.push_back(c); + } + + // WHEN + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + GLShader *targetShader; + + for (int j = 0; j < sortedCommands.size(); ++j) { + + if (j % 4 == 0) { + targetShader = sortedCommands.at(j).m_glShader; + if (j > 0) + QVERIFY(targetShader != sortedCommands.at(j - 1).m_glShader); + } + QCOMPARE(targetShader, sortedCommands.at(j).m_glShader); + } + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + + void checkRenderViewUniformMinification_data() + { + QTest::addColumn>("shaders"); + QTest::addColumn>("rawParameters"); + QTest::addColumn>("expectedMinimizedParameters"); + + Qt3DCore::QNodeId fakeTextureNodeId = Qt3DCore::QNodeId::createId(); + + ShaderParameterPack pack1; + pack1.setUniform(1, UniformValue(883)); + pack1.setUniform(2, UniformValue(1584.0f)); + pack1.setTexture(3, 0, fakeTextureNodeId); + + QShaderProgram *shader1 = new QShaderProgram(); + QShaderProgram *shader2 = new QShaderProgram(); + + shader1->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("1")); + shader2->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("2")); + + ShaderParameterPack minifiedPack1; + + QTest::newRow("NoMinification") + << (QVector() << shader1 << shader2) + << (QVector() << pack1 << pack1) + << (QVector() << pack1 << pack1); + + QTest::newRow("SingleShaderMinified") + << (QVector() << shader1 << shader1 << shader1) + << (QVector() << pack1 << pack1 << pack1) + << (QVector() << pack1 << minifiedPack1 << minifiedPack1); + + QTest::newRow("MultipleShadersMinified") + << (QVector() << shader1 << shader1 << shader1 << shader2 << shader2 << shader2) + << (QVector() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1) + << (QVector() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1); + } + + void checkRenderViewUniformMinification() + { + QFETCH(QVector, shaders); + QFETCH(QVector, rawParameters); + QFETCH(QVector, expectedMinimizedParameters); + + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(&nodeManagers); + + GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager(); + for (int i = 0, m = shaders.size(); i < m; ++i) { + Shader* backend = new Shader(); + backend->setRenderer(&renderer); + simulateInitializationSync(shaders.at(i), backend); + shaderManager->createOrAdoptExisting(backend); + } + + RenderView renderView; + QVector rawCommands; + renderView.setRenderer(&renderer); + + for (int i = 0, m = shaders.size(); i < m; ++i) { + RenderCommand c; + c.m_shaderId = shaders.at(i)->id(); + c.m_glShader = shaderManager->lookupResource(c.m_shaderId); + c.m_parameterPack = rawParameters.at(i); + rawCommands.push_back(c); + } + + // WHEN + renderView.setCommands(rawCommands); + renderView.addSortType((QVector() << QSortPolicy::Uniform)); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands, sortedCommands); + + for (int i = 0, m = shaders.size(); i < m; ++i) { + const RenderCommand c = sortedCommands.at(i); + QCOMPARE(c.m_shaderId, shaders.at(i)->id()); + compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); + } + + renderer.shutdown(); + } + + + void checkRenderCommandFrontToBackSorting() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + QVector rawCommands; + QVector sortTypes; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + sortTypes.push_back(QSortPolicy::FrontToBack); + + for (int i = 0; i < 200; ++i) { + RenderCommand c; + c.m_depth = float(i); + rawCommands.push_back(c); + } + + // WHEN + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + for (int j = 1; j < sortedCommands.size(); ++j) + QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth); + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + + void checkRenderCommandStateCostSorting() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + QVector rawCommands; + QVector sortTypes; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + sortTypes.push_back(QSortPolicy::StateChangeCost); + + for (int i = 0; i < 200; ++i) { + RenderCommand c; + c.m_changeCost = i; + rawCommands.push_back(c); + } + + // WHEN + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + for (int j = 1; j < sortedCommands.size(); ++j) + QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost); + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + + void checkRenderCommandCombinedStateMaterialDepthSorting() + { + // GIVEN + Qt3DRender::Render::NodeManagers nodeManagers; + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + RenderView renderView; + QVector rawCommands; + QVector sortTypes; + + renderer.setNodeManagers(&nodeManagers); + renderView.setRenderer(&renderer); + + sortTypes.push_back(QSortPolicy::StateChangeCost); + sortTypes.push_back(QSortPolicy::Material); + sortTypes.push_back(QSortPolicy::BackToFront); + + GLShader *dna[5] = { + reinterpret_cast(0x250), + reinterpret_cast(0x500), + reinterpret_cast(0x1000), + reinterpret_cast(0x1500), + reinterpret_cast(0x2000) + }; + + float depth[3] = { + 10.0f, + 25.0f, + 30.0f + }; + + int stateChangeCost[2] = { + 100, + 200 + }; + + auto buildRC = [] (GLShader *dna, float depth, int changeCost) { + RenderCommand c; + c.m_glShader = dna; + c.m_depth = depth; + c.m_changeCost = changeCost; + return c; + }; + + RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]); + RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]); + RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]); + RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]); + RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]); + + RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]); + RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]); + RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]); + RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); + RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); + + rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9; + + // WHEN + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + + // Ordered by higher state, higher shaderDNA and higher depth + QCOMPARE(c0, sortedCommands.at(4)); + QCOMPARE(c3, sortedCommands.at(1)); + QCOMPARE(c4, sortedCommands.at(2)); + QCOMPARE(c5, sortedCommands.at(0)); + QCOMPARE(c8, sortedCommands.at(3)); + + QCOMPARE(c1, sortedCommands.at(7)); + QCOMPARE(c2, sortedCommands.at(5)); + QCOMPARE(c6, sortedCommands.at(9)); + QCOMPARE(c7, sortedCommands.at(8)); + QCOMPARE(c9, sortedCommands.at(6)); + + // RenderCommands are deleted by RenderView dtor + renderer.shutdown(); + } + + void checkRenderCommandTextureSorting() + { + // GIVEN + RenderView renderView; + QVector sortTypes; + + sortTypes.push_back(QSortPolicy::Texture); + + + Qt3DCore::QNodeId tex1 = Qt3DCore::QNodeId::createId(); + Qt3DCore::QNodeId tex2 = Qt3DCore::QNodeId::createId(); + Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId(); + Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId(); + + RenderCommand a; + { + ShaderParameterPack pack; + pack.setTexture(0, 0, tex1); + pack.setTexture(1, 0, tex3); + pack.setTexture(2, 0, tex4); + pack.setTexture(3, 0, tex2); + a.m_parameterPack = pack; + } + RenderCommand b; + RenderCommand c; + { + ShaderParameterPack pack; + pack.setTexture(0, 0, tex1); + pack.setTexture(3, 0, tex2); + c.m_parameterPack = pack; + } + RenderCommand d; + { + ShaderParameterPack pack; + pack.setTexture(1, 0, tex3); + pack.setTexture(2, 0, tex4); + d.m_parameterPack = pack; + } + RenderCommand e; + { + ShaderParameterPack pack; + pack.setTexture(3, 0, tex2); + e.m_parameterPack = pack; + } + RenderCommand f; + { + ShaderParameterPack pack; + pack.setTexture(3, 0, tex2); + f.m_parameterPack = pack; + } + RenderCommand g; + { + ShaderParameterPack pack; + pack.setTexture(0, 0, tex1); + pack.setTexture(1, 0, tex3); + pack.setTexture(2, 0, tex4); + pack.setTexture(3, 0, tex2); + g.m_parameterPack = pack; + } + + // WHEN + QVector rawCommands = {a, b, c, d, e, f, g}; + renderView.addSortType(sortTypes); + renderView.setCommands(rawCommands); + renderView.sort(); + + // THEN + const QVector sortedCommands = renderView.commands(); + QCOMPARE(rawCommands.size(), sortedCommands.size()); + QCOMPARE(sortedCommands.at(0), a); + QCOMPARE(sortedCommands.at(1), g); + QCOMPARE(sortedCommands.at(2), d); + QCOMPARE(sortedCommands.at(3), c); + QCOMPARE(sortedCommands.at(4), e); + QCOMPARE(sortedCommands.at(5), f); + QCOMPARE(sortedCommands.at(6), b); + // RenderCommands are deleted by RenderView dtor + } +private: +}; + +} // Render + +} // Qt3DRender + +QT_END_NAMESPACE + +//APPLESS_ +QTEST_MAIN(Qt3DRender::Render::tst_RenderViews) + +#include "tst_renderviews.moc" diff --git a/tests/auto/render/opengl/renderviewutils/renderviewutils.pro b/tests/auto/render/opengl/renderviewutils/renderviewutils.pro new file mode 100644 index 000000000..e9c9f8d51 --- /dev/null +++ b/tests/auto/render/opengl/renderviewutils/renderviewutils.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_renderviewutils + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_renderviewutils.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp new file mode 100644 index 000000000..8a345d840 --- /dev/null +++ b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp @@ -0,0 +1,801 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "testrenderer.h" +#include "testpostmanarbiter.h" + +class tst_RenderViewUtils : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT +private Q_SLOTS: + void topLevelScalarValueNoUniforms(); + void topLevelScalarValue(); + void topLevelTextureValueNoUniforms(); + void topLevelTextureValue(); + void topLevelArrayValue(); + void nestedShaderDataValue(); + void topLevelStructValue_data(); + void topLevelStructValue(); + void topLevelDynamicProperties(); + void transformedProperties(); + void shouldNotifyDynamicPropertyChanges(); + +private: + void initBackendShaderData(Qt3DRender::Render::AbstractRenderer *renderer, + Qt3DRender::QShaderData *frontend, + Qt3DRender::Render::ShaderDataManager *manager) + { + // Create children first + for (QObject *c : frontend->children()) { + Qt3DRender::QShaderData *cShaderData = qobject_cast(c); + if (cShaderData) + initBackendShaderData(renderer, cShaderData, manager); + } + + // Create backend element for frontend one + Qt3DRender::Render::ShaderData *backend = manager->getOrCreateResource(frontend->id()); + // Init the backend element + backend->setRenderer(renderer); + simulateInitializationSync(frontend, backend); + } + + void initBackendTexture(Qt3DRender::QAbstractTexture *frontend, + Qt3DRender::Render::TextureManager *manager) + { + // Create backend element for frontend one + Qt3DRender::Render::Texture *backend = manager->getOrCreateResource(frontend->id()); + // Init the backend element + simulateInitialization(frontend, backend); + } +}; + +class ScalarShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(float scalar READ scalar WRITE setScalar NOTIFY scalarChanged) + +public: + ScalarShaderData(Qt3DCore::QNode *parent = nullptr) + : Qt3DRender::QShaderData(parent) + , m_scalar(0.0f) + { + } + + void setScalar(float scalar) + { + if (scalar != m_scalar) { + m_scalar = scalar; + emit scalarChanged(); + } + } + + float scalar() const + { + return m_scalar; + } + + QHash buildUniformMap(const QString &blockName) + { + QHash uniforms; + + uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + +Q_SIGNALS: + void scalarChanged(); + +private: + float m_scalar; +}; + +class TextureShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QAbstractTexture* texture READ texture WRITE setTexture NOTIFY textureChanged) + +public: + TextureShaderData() + : Qt3DRender::QShaderData() + , m_texture(nullptr) + { + } + + void setTexture(Qt3DRender::QAbstractTexture *texture) + { + if (texture != m_texture) { + m_texture = texture; + emit textureChanged(); + } + } + + Qt3DRender::QAbstractTexture *texture() const + { + return m_texture; + } + + QHash buildUniformMap(const QString &blockName) + { + QHash uniforms; + + uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + +Q_SIGNALS: + void textureChanged(); + +private: + Qt3DRender::QAbstractTexture *m_texture; +}; + + +class ArrayShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(QVariantList array READ array WRITE setArray NOTIFY arrayChanged) + +public: + ArrayShaderData() + : Qt3DRender::QShaderData() + { + } + + void setArray(const QVariantList &array) + { + if (array != m_array) { + m_array = array; + emit arrayChanged(); + } + } + + QVariantList array() const + { + return m_array; + } + + QHash buildUniformMap(const QString &blockName) + { + QHash uniforms; + + uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + +Q_SIGNALS: + void arrayChanged(); + +private: + QVariantList m_array; +}; + +class StructShaderData : public Qt3DRender::QShaderData +{ + Q_OBJECT + Q_PROPERTY(float scalar READ scalar WRITE setScalar NOTIFY scalarChanged) + Q_PROPERTY(QVariantList array READ array WRITE setArray NOTIFY arrayChanged) + +public: + StructShaderData() + : Qt3DRender::QShaderData() + , m_scalar(0.0f) + { + } + + void setScalar(float scalar) + { + if (scalar != m_scalar) { + m_scalar = scalar; + emit scalarChanged(); + } + } + + float scalar() const + { + return m_scalar; + } + + void setArray(const QVariantList &array) + { + if (array != m_array) { + m_array = array; + emit arrayChanged(); + } + } + + QVariantList array() const + { + return m_array; + } + + virtual QHash buildUniformMap(const QString &blockName) + { + QHash uniforms; + + uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); + + return uniforms; + } + + virtual QHash buildUniformMapValues(const QString &blockName) + { + QHash uniforms; + + uniforms.insert(blockName + QStringLiteral(".scalar"), QVariant(scalar())); + uniforms.insert(blockName + QStringLiteral(".array[0]"), QVariant(array())); + + return uniforms; + } + +Q_SIGNALS: + void scalarChanged(); + void arrayChanged(); + +private: + float m_scalar; + QVariantList m_array; +}; + +class MultiLevelStructShaderData : public StructShaderData +{ + Q_OBJECT + Q_PROPERTY(Qt3DRender::QShaderData *inner READ inner WRITE setInner NOTIFY innerChanged) + +public: + MultiLevelStructShaderData() + : StructShaderData() + , m_inner(nullptr) + { + } + + void setInner(Qt3DRender::QShaderData *inner) + { + if (inner != m_inner) { + m_inner = inner; + emit innerChanged(); + } + } + + Qt3DRender::QShaderData *inner() const + { + return m_inner; + } + + QHash buildUniformMap(const QString &blockName) override + { + QHash innerUniforms; + + StructShaderData *innerData = nullptr; + if ((innerData = qobject_cast(m_inner)) != nullptr) + innerUniforms = innerData->buildUniformMap(QStringLiteral(".inner")); + + QHash uniforms = StructShaderData::buildUniformMap(blockName); + QHash::const_iterator it = innerUniforms.begin(); + const QHash::const_iterator end = innerUniforms.end(); + + while (it != end) { + uniforms.insert(blockName + it.key(), it.value()); + ++it; + } + return uniforms; + } + + QHash buildUniformMapValues(const QString &blockName) override + { + QHash innerUniformsValues; + + StructShaderData *innerData = nullptr; + if ((innerData = qobject_cast(m_inner)) != nullptr) + innerUniformsValues = innerData->buildUniformMapValues(QStringLiteral(".inner")); + + QHash uniformsValues = StructShaderData::buildUniformMapValues(blockName); + QHash::const_iterator it = innerUniformsValues.begin(); + const QHash::const_iterator end = innerUniformsValues.end(); + + while (it != end) { + uniformsValues.insert(blockName + it.key(), it.value()); + ++it; + } + + return uniformsValues; + } + +Q_SIGNALS: + void innerChanged(); + +private: + Qt3DRender::QShaderData *m_inner; +}; + +void tst_RenderViewUtils::topLevelScalarValueNoUniforms() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new ScalarShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + shaderData->setScalar(883.0f); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEB + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); + + // THEN + // activeUniformNamesToValue should be empty as blockBuilder.uniforms is + QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); +} + +void tst_RenderViewUtils::topLevelScalarValue() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new ScalarShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + shaderData->setScalar(883.0f); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 1); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), QVariant(shaderData->scalar())); + ++it; + } +} + +void tst_RenderViewUtils::topLevelTextureValueNoUniforms() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new TextureShaderData); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer texture(new Qt3DRender::QTexture2D); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + shaderData->setTexture(texture.data()); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEB + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); + + // THEN + // activeUniformNamesToValue should be empty as blockBuilder.uniforms is + QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); +} + +void tst_RenderViewUtils::topLevelTextureValue() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new TextureShaderData); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager); + QScopedPointer texture(new Qt3DRender::QTexture2D); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + initBackendTexture(texture.data(), textureManager.data()); + shaderData->setTexture(texture.data()); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 1); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), QVariant::fromValue(shaderData->texture()->id())); + ++it; + } +} + +void tst_RenderViewUtils::topLevelArrayValue() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new ArrayShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; + shaderData->setArray(arrayValues); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 1); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), QVariant(arrayValues)); + ++it; + } +} + +void tst_RenderViewUtils::nestedShaderDataValue() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer arrayShaderData(new ArrayShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + QScopedPointer shaderData1(new ScalarShaderData(arrayShaderData.data())); + QScopedPointer shaderData2(new ScalarShaderData(arrayShaderData.data())); + QScopedPointer shaderData3(new ScalarShaderData(arrayShaderData.data())); + + shaderData1->setScalar(883.0f); + shaderData2->setScalar(1200.0f); + shaderData3->setScalar(1340.0f); + QHash scalarValues; + scalarValues[QStringLiteral("MyBlock.array[0].scalar")] = shaderData1->scalar(); + scalarValues[QStringLiteral("MyBlock.array[1].scalar")] = shaderData2->scalar(); + scalarValues[QStringLiteral("MyBlock.array[2].scalar")] = shaderData3->scalar(); + + + const Qt3DCore::QNodeId id1 = shaderData1->id(); + const Qt3DCore::QNodeId id2 = shaderData2->id(); + const Qt3DCore::QNodeId id3 = shaderData3->id(); + + // WHEN + const QVariantList arrayValues = QVariantList() << QVariant::fromValue(id1) << QVariant::fromValue(id2) << QVariant::fromValue(id3); + arrayShaderData->setArray(arrayValues); + initBackendShaderData(&renderer, arrayShaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendArrayShaderData = manager->lookupResource(arrayShaderData->id()); + Qt3DRender::Render::ShaderData *backendShaderData1 = manager->lookupResource(id1); + Qt3DRender::Render::ShaderData *backendShaderData2 = manager->lookupResource(id2); + Qt3DRender::Render::ShaderData *backendShaderData3 = manager->lookupResource(id3); + QVERIFY(backendArrayShaderData != nullptr); + QVERIFY(backendShaderData1 != nullptr); + QVERIFY(backendShaderData2 != nullptr); + QVERIFY(backendShaderData3 != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::ShaderUniform()); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendArrayShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 3); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); + + // WHEN + auto it = blockBuilder.uniforms.cbegin(); + const auto end = blockBuilder.uniforms.cend(); + + while (it != end) { + // THEN + const int nameId = Qt3DRender::Render::StringToInt::lookupId(it.key()); + QVERIFY(blockBuilder.activeUniformNamesToValue.contains(nameId)); + QCOMPARE(blockBuilder.activeUniformNamesToValue[nameId], scalarValues.value(it.key())); + ++it; + } +} + +void tst_RenderViewUtils::topLevelStructValue_data() +{ + QTest::addColumn("shaderData"); + QTest::addColumn("blockName"); + + QVariantList arrayValues2 = QVariantList() << 180 << 220 << 250 << 270 << 300 << 350 << 550; + QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; + + MultiLevelStructShaderData *twoLevelsNestedShaderData = new MultiLevelStructShaderData(); + MultiLevelStructShaderData *singleLevelShaderData = new MultiLevelStructShaderData(); + StructShaderData *shaderData = new StructShaderData(); + + // Don't forget to set the parent so that initBackendShaderData + // properly initializes nested members + shaderData->setParent(singleLevelShaderData); + shaderData->setArray(arrayValues); + shaderData->setScalar(1584.0f); + + singleLevelShaderData->setParent(twoLevelsNestedShaderData); + singleLevelShaderData->setInner(shaderData); + singleLevelShaderData->setScalar(1200.0f); + singleLevelShaderData->setArray(arrayValues2); + + twoLevelsNestedShaderData->setInner(singleLevelShaderData); + twoLevelsNestedShaderData->setArray(arrayValues + arrayValues2); + twoLevelsNestedShaderData->setScalar(1340.0f); + + QTest::newRow("simple struct") << shaderData << QStringLiteral("Block"); + QTest::newRow("single level inner struct") << (StructShaderData *)singleLevelShaderData << QStringLiteral("Block"); + QTest::newRow("tow level inner struct") << (StructShaderData *)twoLevelsNestedShaderData << QStringLiteral("Block"); +} + +void tst_RenderViewUtils::topLevelStructValue() +{ + // GIVEN + TestRenderer renderer; + QFETCH(StructShaderData *, shaderData); + QFETCH(QString, blockName); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + initBackendShaderData(&renderer, shaderData, manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms = shaderData->buildUniformMap(blockName); + const QHash expectedValues = shaderData->buildUniformMapValues(blockName); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, blockName); + + // THEN + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), blockBuilder.uniforms.count()); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + + while (it != end) { + // THEN + QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QVERIFY(expectedValues.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + QCOMPARE(it.value(), expectedValues.value(Qt3DRender::Render::StringToInt::lookupString(it.key()))); + ++it; + } +} + +void tst_RenderViewUtils::topLevelDynamicProperties() +{ + // GIVEN + TestRenderer renderer; + QScopedPointer shaderData(new Qt3DRender::QShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + QScopedPointer texture(new Qt3DRender::QTexture2D); + QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); + + // WHEN + initBackendTexture(texture.data(), textureManager.data()); + shaderData->setProperty("scalar", 883.0f); + shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + + // WHEN + Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + blockBuilder.shaderDataManager = manager.data(); + blockBuilder.textureManager = textureManager.data(); + blockBuilder.updatedPropertiesOnly = false; + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::ShaderUniform()); + // build name-value map + blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); + + // THEN + QVERIFY(blockBuilder.uniforms.count() == 3); + QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); + + QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.scalar")), + shaderData->property("scalar")); + QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.array[0]")), + shaderData->property("array")); + QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.texture")), + QVariant::fromValue(texture->id())); +} + +void tst_RenderViewUtils::transformedProperties() +{ + // GIVEN + QScopedPointer shaderData(new Qt3DRender::QShaderData()); + QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); + TestRenderer renderer; + + // WHEN + const Vector3D position = Vector3D(15.0f, -5.0f, 10.0f); + const QVector3D positionQt = convertToQVector3D(position); + Matrix4x4 worldMatrix; + { + QMatrix4x4 m; + m.translate(-3.0f, 2.0f, 7.5f); + worldMatrix = Matrix4x4(m); + } + Matrix4x4 viewMatrix; + { + QMatrix4x4 m; + m.translate(9.0f, 6.0f, 12.0f); + viewMatrix = Matrix4x4(m); + } + + shaderData->setProperty("position0", positionQt); + shaderData->setProperty("position1", positionQt); + shaderData->setProperty("position2", positionQt); + shaderData->setProperty("position3", positionQt); + shaderData->setProperty("position1Transformed", Qt3DRender::Render::ShaderData::ModelToEye); + shaderData->setProperty("position2Transformed", Qt3DRender::Render::ShaderData::ModelToWorld); + shaderData->setProperty("position3Transformed", Qt3DRender::Render::ShaderData::ModelToWorldDirection); + initBackendShaderData(&renderer, shaderData.data(), manager.data()); + + // THEN + Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); + QVERIFY(backendShaderData != nullptr); + QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position0")), Qt3DRender::Render::ShaderData::NoTransform); + QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position1")), Qt3DRender::Render::ShaderData::ModelToEye); + QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position2")), Qt3DRender::Render::ShaderData::ModelToWorld); + QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position3")), Qt3DRender::Render::ShaderData::ModelToWorldDirection); + + // WHEN + backendShaderData->updateWorldTransform(worldMatrix); + const Vector3D position1Value = backendShaderData->getTransformedProperty(QStringLiteral("position1"), viewMatrix).value(); + const Vector3D position2Value = backendShaderData->getTransformedProperty(QStringLiteral("position2"), viewMatrix).value(); + const Vector3D position3Value = backendShaderData->getTransformedProperty(QStringLiteral("position3"), viewMatrix).value(); + const QVariant position0Value = backendShaderData->getTransformedProperty(QStringLiteral("position0"), viewMatrix); + + // THEN + QCOMPARE(position0Value, positionQt); + QCOMPARE(position1Value, viewMatrix * worldMatrix * position); + QCOMPARE(position2Value, worldMatrix * position); + QCOMPARE(position3Value, Vector3D((worldMatrix * Vector4D(position, 0.0f)))); +} + +void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges() +{ + // GIVEN + TestArbiter arbiter; + QScopedPointer shaderData(new Qt3DRender::QShaderData()); + arbiter.setArbiterOnNode(shaderData.data()); + + // WHEN + shaderData->setProperty("scalar", 883.0f); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data()); + + arbiter.dirtyNodes.clear(); + + // WHEN + QScopedPointer texture(new Qt3DRender::QTexture2D); + shaderData->setProperty("texture", QVariant::fromValue(texture.data())); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + QCOMPARE(arbiter.dirtyNodes.size(), 1); + QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data()); +} + +QTEST_MAIN(tst_RenderViewUtils) + +#include "tst_renderviewutils.moc" diff --git a/tests/auto/render/opengl/textures/textures.pro b/tests/auto/render/opengl/textures/textures.pro new file mode 100644 index 000000000..a116756af --- /dev/null +++ b/tests/auto/render/opengl/textures/textures.pro @@ -0,0 +1,15 @@ +TEMPLATE = app + +TARGET = tst_textures + +QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib + +CONFIG += testcase + +SOURCES += tst_textures.cpp + +include(../../../core/common/common.pri) +include(../../commons/commons.pri) + +# Link Against OpenGL Renderer Plugin +include(../opengl_render_plugin.pri) diff --git a/tests/auto/render/opengl/textures/tst_textures.cpp b/tests/auto/render/opengl/textures/tst_textures.cpp new file mode 100644 index 000000000..984d49a3e --- /dev/null +++ b/tests/auto/render/opengl/textures/tst_textures.cpp @@ -0,0 +1,821 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $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$ +** +****************************************************************************/ + +// TODO Remove in Qt6 +#include +QT_WARNING_DISABLE_DEPRECATED + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/** + * @brief Dummy QTextureImageDataGenerator + */ +class TestImageDataGenerator : public Qt3DRender::QTextureImageDataGenerator +{ + int m_id; +public: + TestImageDataGenerator(int id) : m_id(id) {} + + Qt3DRender::QTextureImageDataPtr operator ()() override { + return Qt3DRender::QTextureImageDataPtr::create(); + } + + bool operator ==(const Qt3DRender::QTextureImageDataGenerator &other) const override { + const TestImageDataGenerator *otherFunctor = Qt3DRender::functor_cast(&other); + return (otherFunctor != nullptr && otherFunctor->m_id == m_id); + } + + QT3D_FUNCTOR(TestImageDataGenerator) +}; + +/** + * @brief Dummy QTextureGenerator + */ +class TestTextureGenerator : public Qt3DRender::QTextureGenerator +{ + int m_id; +public: + TestTextureGenerator(int id) : m_id(id) {} + + Qt3DRender::QTextureDataPtr operator ()() override { + return Qt3DRender::QTextureDataPtr::create(); + } + + bool operator ==(const Qt3DRender::QTextureGenerator &other) const override { + const TestTextureGenerator *otherFunctor = Qt3DRender::functor_cast(&other); + return (otherFunctor != nullptr && otherFunctor->m_id == m_id); + } + + QT3D_FUNCTOR(TestTextureGenerator) +}; + +typedef QSharedPointer TestTextureGeneratorPtr; + +class TestTexturePrivate : public Qt3DRender::QAbstractTexturePrivate +{ +public: + int genId; +}; + +/** + * @brief Test QTexture. Assign texture data functor if genId > 0. + */ +class TestTexture : public Qt3DRender::QAbstractTexture +{ +public: + TestTexture(int genId, Qt3DCore::QNode *p = nullptr) + : QAbstractTexture(*new TestTexturePrivate(), p) + { + d_func()->genId = genId; + if (genId > 0) + d_func()->setDataFunctor(TestTextureGeneratorPtr::create(genId)); + } +private: + Q_DECLARE_PRIVATE(TestTexture) +}; + +class TestSharedGLTexturePrivate : public Qt3DRender::QAbstractTexturePrivate +{ +}; + +class TestSharedGLTexture : public Qt3DRender::QAbstractTexture +{ +public: + TestSharedGLTexture(int textureId, Qt3DCore::QNode *p = nullptr) + : QAbstractTexture(*new TestSharedGLTexturePrivate(), p) + { + d_func()->m_sharedTextureId = textureId; + } + +private: + Q_DECLARE_PRIVATE(TestSharedGLTexture) +}; + + +/** + * @brief Test QTextureImage + */ +class TestTextureImage : public Qt3DRender::QAbstractTextureImage +{ +public: + TestTextureImage(int genId, Qt3DCore::QNode *p = nullptr) + : QAbstractTextureImage(p) + , m_genId(genId) + { + } + + void updateGenerator() + { + Qt3DRender::QAbstractTextureImage::notifyDataGeneratorChanged(); + } + + Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const + { + return Qt3DRender::QTextureImageDataGeneratorPtr(new TestImageDataGenerator(m_genId)); + } +protected: + int m_genId; +}; + +class EmptyTextureImage : public Qt3DRender::QAbstractTextureImage +{ +public: + EmptyTextureImage(Qt3DCore::QNode *p = nullptr) + : QAbstractTextureImage(p) + { + } + + Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const + { + return {}; + } +}; + +class tst_RenderTextures : public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + + Qt3DRender::QAbstractTexture *createQTexture(int genId, + const QVector &imgGenIds, + bool genMipMaps) + { + TestTexture *tex = new TestTexture(genId); + + for (int imgGen : imgGenIds) + tex->addTextureImage(new TestTextureImage(imgGen)); + tex->setGenerateMipMaps(genMipMaps); + + return tex; + } + + Qt3DRender::QAbstractTexture *createQTextureWithTextureId(int textureId) + { + return new TestSharedGLTexture(textureId); + } + + Qt3DRender::Render::Texture *createBackendTexture(Qt3DRender::QAbstractTexture *frontend, + Qt3DRender::Render::TextureManager *texMgr, + Qt3DRender::Render::TextureImageManager *texImgMgr, + Qt3DRender::Render::AbstractRenderer *renderer) + { + Qt3DRender::Render::Texture *backend = texMgr->getOrCreateResource(frontend->id()); + backend->setRenderer(renderer); + simulateInitializationSync(frontend, backend); + + // create texture images + for (const auto texImgFrontend : frontend->textureImages()) { + // make sure TextureImageManager has backend node for this QTextureImage + if (!texImgMgr->contains(texImgFrontend->id())) { + Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id()); + texImgBackend->setRenderer(renderer); + simulateInitializationSync(texImgFrontend, texImgBackend); + } + } + + return backend; + } + +private Q_SLOTS: + + void shouldCreateSameGLTextures() + { + QSKIP("Texture Sharing is now disabled"); + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(mgrs.data()); + + // GIVEN + Qt3DRender::QAbstractTexture *tex1a = createQTexture(-1, {1,2}, true); + Qt3DRender::QAbstractTexture *tex1b = createQTexture(-1, {1,2}, true); + + // WHEN + Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + renderer.updateTexture(bt1a); + renderer.updateTexture(bt1b); + + // THEN + QCOMPARE(renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1a->peerId()), + renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1b->peerId())); + renderer.shutdown(); + } + + void shouldCreateDifferentGLTexturess() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(mgrs.data()); + + // GIVEN + QVector textures; + textures << createQTexture(-1, {1,2}, true); + textures << createQTexture(-1, {1,2}, false); + textures << createQTexture(1, {1,2}, true); + textures << createQTexture(1, {1,2}, false); + textures << createQTexture(1, {1,2,3}, true); + textures << createQTexture(1, {1,2,3}, false); + + // WHEN + QVector backend; + for (auto *t : textures) { + Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + backend.push_back(backendTexture); + renderer.updateTexture(backendTexture); + } + + // THEN + + // no 2 textures must be the same + for (int i = 0; i < backend.size(); i++) + for (int k = i+1; k < backend.size(); k++) + QVERIFY(renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[i]->peerId()) != + renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[k]->peerId())); + + QVector glTextures; + for (Qt3DRender::Render::Texture *t : backend) + glTextures.push_back(renderer.glResourceManagers()->glTextureManager()->lookupResource(t->peerId())); + + // some texture generators must be the same + QVERIFY(glTextures[0]->textureGenerator().data() == nullptr); + QVERIFY(glTextures[1]->textureGenerator().data() == nullptr); + QCOMPARE(*(glTextures[2]->textureGenerator()), *(glTextures[3]->textureGenerator())); + + // some images must be the same + QCOMPARE(glTextures[0]->images(), glTextures[1]->images()); + QCOMPARE(glTextures[0]->images(), glTextures[2]->images()); + QCOMPARE(glTextures[0]->images(), glTextures[3]->images()); + QCOMPARE(glTextures[4]->images(), glTextures[5]->images()); + + QCOMPARE(glTextures[0]->properties(), glTextures[2]->properties()); + QCOMPARE(glTextures[1]->properties(), glTextures[3]->properties()); + QVERIFY(glTextures[0]->properties() != glTextures[1]->properties()); + + renderer.shutdown(); + } + + void shouldCreateDifferentGLTexturesWhenUsingSharedTextureIds() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(mgrs.data()); + + Qt3DRender::Render::GLResourceManagers *glMgrs = renderer.glResourceManagers(); + + // both texture having the same sharedTextureId + { + // GIVEN + Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1); + Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(1); + + // WHEN + Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + // THEN + QCOMPARE(bt1->sharedTextureId(), 1); + QCOMPARE(bt2->sharedTextureId(), 1); + + // WHEN + renderer.updateTexture(bt1); + renderer.updateTexture(bt2); + + // THEN + Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); + QVERIFY(glt1 != glt2); + QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); + QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); + } + + // textures having a different sharedTextureId + { + // GIVEN + Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1); + Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(2); + + // WHEN + Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + // THEN + QCOMPARE(bt1->sharedTextureId(), 1); + QCOMPARE(bt2->sharedTextureId(), 2); + + // WHEN + renderer.updateTexture(bt1); + renderer.updateTexture(bt2); + + // THEN + Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); + QVERIFY(glt1 != glt2); + QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); + QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); + } + + renderer.shutdown(); + } + + void generatorsShouldCreateSameData() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + renderer.setNodeManagers(mgrs.data()); + + // GIVEN + QVector textures; + textures << createQTexture(1, {1}, true); + textures << createQTexture(2, {1,2}, true); + textures << createQTexture(1, {1,2}, true); + + // WHEN + QVector backend; + for (auto *t : textures) { + Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, + mgrs->textureManager(), + mgrs->textureImageManager(), + &renderer); + backend.push_back(backendTexture); + renderer.updateTexture(backendTexture); + } + + Qt3DRender::QTextureImageDataGeneratorPtr idg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->images()[0].generator; + Qt3DRender::QTextureImageDataGeneratorPtr idg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[0].generator; + Qt3DRender::QTextureImageDataGeneratorPtr idg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[1].generator; + Qt3DRender::QTextureGeneratorPtr tg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->textureGenerator(); + Qt3DRender::QTextureGeneratorPtr tg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[2]->peerId())->textureGenerator(); + Qt3DRender::QTextureGeneratorPtr tg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->textureGenerator(); + + // THEN + QVERIFY(idg1a); + QVERIFY(idg1b); + QVERIFY(idg2); + QVERIFY(tg1a); + QVERIFY(tg1b); + QVERIFY(tg2); + + QCOMPARE(*idg1a, *idg1b); + QVERIFY(!(*idg1a == *idg2)); + QCOMPARE(*tg1a, *tg1b); + QVERIFY(!(*tg1a == *tg2)); + + renderer.shutdown(); + } + + void checkTextureImageInitialState() + { + // GIVEN + Qt3DRender::Render::TextureImage img; + + // THEN + QCOMPARE(img.layer(), 0); + QCOMPARE(img.mipLevel(), 0); + QCOMPARE(img.isDirty(), false); + QCOMPARE(img.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); + QVERIFY(img.dataGenerator().isNull()); + } + + void checkTextureImageCleanupState() + { + // GIVEN + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + TestTextureImage img(1); + img.setLayer(2); + img.setMipLevel(3); + + // WHEN + Qt3DRender::Render::TextureImage texImgBackend; + texImgBackend.setRenderer(&renderer); + simulateInitializationSync(&img, &texImgBackend); + texImgBackend.cleanup(); + + // THEN + QCOMPARE(texImgBackend.isDirty(), false); + QCOMPARE(texImgBackend.layer(), 0); + QCOMPARE(texImgBackend.mipLevel(), 0); + QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); + QVERIFY(texImgBackend.dataGenerator().isNull()); + + renderer.shutdown(); + } + + void checkTextureImageInitializeFromPeer() + { + // GIVEN + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + TestTextureImage img(1); + + { + // WHEN + img.setLayer(2); + img.setMipLevel(3); + + Qt3DRender::Render::TextureImage texImgBackend; + texImgBackend.setRenderer(&renderer); + simulateInitializationSync(&img, &texImgBackend); + + // THEN + QCOMPARE(texImgBackend.isEnabled(), true); + QCOMPARE(texImgBackend.isDirty(), true); + QCOMPARE(texImgBackend.peerId(), img.id()); + QCOMPARE(texImgBackend.layer(), 2); + QCOMPARE(texImgBackend.mipLevel(), 3); + QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); + QVERIFY(!texImgBackend.dataGenerator().isNull()); + } + + { + // WHEN + img.setEnabled(false); + + Qt3DRender::Render::TextureImage texImgBackend; + texImgBackend.setRenderer(&renderer); + simulateInitializationSync(&img, &texImgBackend); + + // THEN + QCOMPARE(texImgBackend.isEnabled(), false); + QCOMPARE(texImgBackend.peerId(), img.id()); + } + + renderer.shutdown(); + } + + void checkTextureImageSceneChangeEvents() + { + // GIVEN + Qt3DRender::Render::TextureImage backendImage; + TestTextureImage textureImage(1); + TestRenderer renderer; + backendImage.setRenderer(&renderer); + simulateInitializationSync(&textureImage, &backendImage); + + { + // WHEN + const bool newValue = false; + textureImage.setEnabled(newValue); + backendImage.syncFromFrontEnd(&textureImage, false); + + // THEN + QCOMPARE(backendImage.isEnabled(), newValue); + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + } + + { + // WHEN + const int newValue = 7; + textureImage.setLayer(newValue); + backendImage.syncFromFrontEnd(&textureImage, false); + + // THEN + QCOMPARE(backendImage.layer(), newValue); + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + } + + { + // WHEN + const int newValue = 3; + textureImage.setMipLevel(newValue); + backendImage.syncFromFrontEnd(&textureImage, false); + + + // THEN + QCOMPARE(backendImage.mipLevel(), newValue); + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + } + + { + // WHEN + const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeX; + textureImage.setFace(newValue); + backendImage.syncFromFrontEnd(&textureImage, false); + + // THEN + QCOMPARE(backendImage.face(), newValue); + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + } + + { + // WHEN + textureImage.updateGenerator(); + backendImage.syncFromFrontEnd(&textureImage, false); + + // THEN + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + + // WHEN + textureImage.updateGenerator(); + backendImage.syncFromFrontEnd(&textureImage, false); + + // THEN + QVERIFY(backendImage.isDirty()); + QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); + renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); + backendImage.unsetDirty(); + } + + renderer.shutdown(); + } + + void checkTextureImageProperlyReleaseGenerator() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); + Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); + renderer.setNodeManagers(mgrs.data()); + + // GIVEN + Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); + + Qt3DRender::Render::Texture *backendTexture = texMgr->getOrCreateResource(frontendTexture->id()); + backendTexture->setRenderer(&renderer); + simulateInitializationSync(frontendTexture, backendTexture); + + // THEN + QCOMPARE(backendTexture->textureImageIds().size(), 1); + QCOMPARE(frontendTexture->textureImages().size(), 1); + + // WHEN + TestTextureImage *texImgFrontend = static_cast(frontendTexture->textureImages().first()); + const Qt3DRender::QTextureImageDataGeneratorPtr frontendGenerator = texImgFrontend->dataGenerator(); + + // THEN + QVERIFY(!frontendGenerator.isNull()); + + // WHEN + Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id()); + texImgBackend->setRenderer(&renderer); + simulateInitializationSync(texImgFrontend, texImgBackend); + + // THEN + qDebug() << frontendGenerator << texImgBackend->dataGenerator(); + const Qt3DRender::QTextureImageDataGeneratorPtr backendGenerator = texImgFrontend->dataGenerator(); + QVERIFY(frontendGenerator != backendGenerator); + QVERIFY(*frontendGenerator == *backendGenerator); + + renderer.shutdown(); + } + + void checkTextureIsMarkedForDeletion() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); + renderer.setNodeManagers(mgrs.data()); + + Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer, + texMgr); + + // GIVEN + Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); + + Qt3DRender::Render::Texture *backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); + backendTexture->setRenderer(&renderer); + simulateInitializationSync(frontendTexture, backendTexture); + + // THEN + QVERIFY(backendTexture != nullptr); + QCOMPARE(texMgr->textureIdsToCleanup().size(), 0); + + QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture); + + // WHEN + textureBackendNodeMapper.destroy(frontendTexture->id()); + + // THEN + QCOMPARE(texMgr->textureIdsToCleanup().size(), 1); + QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id()); + QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr); + + renderer.shutdown(); + } + + void checkTextureDestructionReconstructionWithinSameLoop() + { + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); + renderer.setNodeManagers(mgrs.data()); + + Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer, + texMgr); + + // GIVEN + Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); + + Qt3DRender::Render::Texture *backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); + backendTexture->setRenderer(&renderer); + simulateInitializationSync(frontendTexture, backendTexture); + + // WHEN + textureBackendNodeMapper.destroy(frontendTexture->id()); + + // THEN + QCOMPARE(texMgr->textureIdsToCleanup().size(), 1); + QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id()); + QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr); + + // WHEN + backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); + backendTexture->setRenderer(&renderer); + simulateInitializationSync(frontendTexture, backendTexture); + + // THEN + QVERIFY(backendTexture != nullptr); + QCOMPARE(texMgr->textureIdsToCleanup().size(), 0); + QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture); + + renderer.shutdown(); + } + + void checkTextureImageDirtinessPropagatesToTextures() + { + // GIVEN + QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); + Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); + Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); + renderer.setNodeManagers(mgrs.data()); + + Qt3DRender::QTexture2D *texture1 = new Qt3DRender::QTexture2D(); + TestTextureImage *image1 = new TestTextureImage(1); + + Qt3DRender::QTexture2D *texture2 = new Qt3DRender::QTexture2D(); + TestTextureImage *image2 = new TestTextureImage(2); + + Qt3DRender::QTexture2D *texture3 = new Qt3DRender::QTexture2D(); + + texture1->addTextureImage(image1); + texture2->addTextureImage(image2); + texture3->addTextureImage(image1); + texture3->addTextureImage(image2); + + Qt3DRender::Render::Texture *backendTexture1 = texMgr->getOrCreateResource(texture1->id()); + Qt3DRender::Render::Texture *backendTexture2 = texMgr->getOrCreateResource(texture2->id()); + Qt3DRender::Render::Texture *backendTexture3 = texMgr->getOrCreateResource(texture3->id()); + Qt3DRender::Render::TextureImage *backendImage1 = texImgMgr->getOrCreateResource(image1->id()); + Qt3DRender::Render::TextureImage *backendImage2 = texImgMgr->getOrCreateResource(image2->id()); + + backendTexture1->setRenderer(&renderer); + backendTexture2->setRenderer(&renderer); + backendTexture3->setRenderer(&renderer); + backendImage1->setRenderer(&renderer); + backendImage2->setRenderer(&renderer); + + simulateInitializationSync(texture1, backendTexture1); + simulateInitializationSync(texture2, backendTexture2); + simulateInitializationSync(texture3, backendTexture3); + simulateInitializationSync(image1, backendImage1); + simulateInitializationSync(image2, backendImage2); + + // THEN + QCOMPARE(backendTexture1->textureImageIds().size(), 1); + QCOMPARE(backendTexture1->textureImageIds().first(), image1->id()); + QCOMPARE(backendTexture2->textureImageIds().size(), 1); + QCOMPARE(backendTexture2->textureImageIds().first(), image2->id()); + QCOMPARE(backendTexture3->textureImageIds().size(), 2); + QCOMPARE(backendTexture3->textureImageIds().first(), image1->id()); + QCOMPARE(backendTexture3->textureImageIds().last(), image2->id()); + + // WHEN + backendTexture1->unsetDirty(); + backendTexture2->unsetDirty(); + backendTexture3->unsetDirty(); + backendImage1->unsetDirty(); + backendImage2->unsetDirty(); + + // THEN + QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + + // WHEN + renderer.textureGathererJob()->run(); + + // THEN + QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + + // WHEN + // Make Image1 dirty + image1->updateGenerator(); + backendImage1->syncFromFrontEnd(image1, false); + + // THEN + QVERIFY(backendImage1->isDirty()); + QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + + // WHEN + renderer.textureGathererJob()->run(); + + // THEN + QVERIFY(backendTexture1->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); + QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); + + backendImage1->unsetDirty(); + backendTexture1->unsetDirty(); + backendTexture3->unsetDirty(); + + // WHEN + image2->updateGenerator(); + backendImage2->syncFromFrontEnd(image2, false); + + // THEN + QVERIFY(backendImage2->isDirty()); + QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + + // WHEN + renderer.textureGathererJob()->run(); + + QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); + QVERIFY(backendTexture2->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); + QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); + + renderer.shutdown(); + } +}; + +QTEST_MAIN(tst_RenderTextures) + +#include "tst_textures.moc" diff --git a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp index 5191b1a36..f1587c27c 100644 --- a/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp +++ b/tests/auto/render/pickboundingvolumejob/tst_pickboundingvolumejob.cpp @@ -45,10 +45,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include diff --git a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp index 1b65388af..51b59bffc 100644 --- a/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp +++ b/tests/auto/render/proximityfiltering/tst_proximityfiltering.cpp @@ -38,6 +38,10 @@ #include #include #include +#include +#include +#include +#include #include #include "testaspect.h" diff --git a/tests/auto/render/qcamera/tst_qcamera.cpp b/tests/auto/render/qcamera/tst_qcamera.cpp index 0dcbce63f..fae8aa14e 100644 --- a/tests/auto/render/qcamera/tst_qcamera.cpp +++ b/tests/auto/render/qcamera/tst_qcamera.cpp @@ -49,6 +49,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE diff --git a/tests/auto/render/qgraphicsutils/qgraphicsutils.pro b/tests/auto/render/qgraphicsutils/qgraphicsutils.pro deleted file mode 100644 index 031a26246..000000000 --- a/tests/auto/render/qgraphicsutils/qgraphicsutils.pro +++ /dev/null @@ -1,9 +0,0 @@ -TEMPLATE = app - -TARGET = tst_qgraphicsutils - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_qgraphicsutils.cpp diff --git a/tests/auto/render/qgraphicsutils/tst_qgraphicsutils.cpp b/tests/auto/render/qgraphicsutils/tst_qgraphicsutils.cpp deleted file mode 100644 index e3676ad3b..000000000 --- a/tests/auto/render/qgraphicsutils/tst_qgraphicsutils.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include - -class tst_QGraphicsUtils : public QObject -{ - Q_OBJECT -private slots: - void fillScalarInDataArray(); - void fillArray(); - void fillScalarWithOffsets(); - void fillMatrix4x4(); - void fillMatrix3x4(); - void fillMatrix4x3(); - void fillMatrixArray(); -}; - -void tst_QGraphicsUtils::fillScalarInDataArray() -{ - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 1; - description.m_offset = 0; - description.m_arrayStride = 10; - - QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); - const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(testVector, 1, 4); - - for (int i = 0; i < 4; i++) { - if (i == 0) - QVERIFY(vectorData[i] == testVector.x()); - else if (i == 1) - QVERIFY(vectorData[i] == testVector.y()); - else if (i == 2) - QVERIFY(vectorData[i] == testVector.z()); - else if (i == 3) - QVERIFY(vectorData[i] == testVector.w()); - } - - QByteArray data(description.m_size * 4 * sizeof(GLfloat), 0); - char *innerData = data.data(); - - // Checked that we are not overflowing - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 2); - for (int i = 0; i < 4; ++i) { - if (i < 2) - QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); - else - QVERIFY(((GLfloat*)innerData)[i] == 0.0f); - } - - // Check that all values are copied - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); - for (int i = 0; i < 4; ++i) - QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); - - // check that offsetting works - description.m_offset = 16; - data = QByteArray(description.m_size * 8 * sizeof(GLfloat), 0); - innerData = data.data(); - - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); - for (int i = 0; i < 8; ++i) { - if (i < 4) - QVERIFY(((GLfloat*)innerData)[i] == 0.0f); - else - QVERIFY(vectorData[i - 4] == ((GLfloat*)innerData)[i]); - } -} - -void tst_QGraphicsUtils::fillArray() -{ - QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); - QVector4D testVector2(3.0f, 5.0f, 0.0f, 7.0f); - QVector4D testVector3(4.0f, 5.0f, 4.0f, 2.0f); - - QVariantList variantList = QVariantList() << testVector << testVector2 << testVector3; - const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant(variantList), 3, 4); - - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 3; - description.m_offset = 16; - description.m_arrayStride = 16; - - QByteArray data(description.m_size * (4 + description.m_arrayStride) * sizeof(GLfloat) + description.m_offset, 0); - char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); - - int offset = description.m_offset / sizeof(GLfloat); - int stride = description.m_arrayStride / sizeof(GLfloat); - - GLfloat *innerDataFloat = (GLfloat*)innerData; - - for (int i = 0; i < 3; ++i) { - for (int j = 0; j < 4; ++j) { - int idx = i * 4 + j; - QVERIFY(innerDataFloat[offset + j] == vectorData[idx]); - } - offset += stride; - } -} - -void tst_QGraphicsUtils::fillScalarWithOffsets() -{ - // Simulates Uniform Block - - // uniform Block { - // vec3 position; // Offset 0 - 12 bytes - // vec3 direction; // Offset 16 - 12 bytes - // vec4 color; // Offset 32 - 16 bytes - // float intensity; // Offset 48 - bytes - // } // total size 64 bytes - - QVector3D position(8.0f, 8.0f, 3.0f); - QVector3D direction(3.0f, 5.0f, 2.0f); - QVector4D color(4.0f, 5.0f, 4.0f, 1.0f); - float intensity = 1.0f; - - Qt3DRender::Render::ShaderUniform posUniform; - posUniform.m_size = 1; - posUniform.m_arrayStride = 0; - posUniform.m_matrixStride = 0; - posUniform.m_offset = 0; - - Qt3DRender::Render::ShaderUniform dirUniform; - dirUniform.m_size = 1; - dirUniform.m_arrayStride = 0; - dirUniform.m_matrixStride = 0; - dirUniform.m_offset = 16; - - Qt3DRender::Render::ShaderUniform colUniform; - colUniform.m_size = 1; - colUniform.m_arrayStride = 0; - colUniform.m_matrixStride = 0; - colUniform.m_offset = 32; - - Qt3DRender::Render::ShaderUniform intUniform; - intUniform.m_size = 1; - intUniform.m_arrayStride = 0; - intUniform.m_matrixStride = 0; - intUniform.m_offset = 48; - - QVector data(16); - void *innerData = data.data(); - - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(position, 1, 3), - posUniform, 3); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(direction, 1, 3), - dirUniform, 3); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(color, 1, 4), - colUniform, 4); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(intensity, 1, 1), - intUniform, 1); - - GLfloat *floatData = (GLfloat*)innerData; - - // Check first 16 bytes - position - QVERIFY(floatData[0] == position.x()); - QVERIFY(floatData[1] == position.y()); - QVERIFY(floatData[2] == position.z()); - QVERIFY(floatData[3] == 0.0f); - // Check 16 - 32 bytes - direction - QVERIFY(floatData[4] == direction.x()); - QVERIFY(floatData[5] == direction.y()); - QVERIFY(floatData[6] == direction.z()); - QVERIFY(floatData[7] == 0.0f); - // Check 32 - 48 bytes - color - QVERIFY(floatData[8] == color.x()); - QVERIFY(floatData[9] == color.y()); - QVERIFY(floatData[10] == color.z()); - QVERIFY(floatData[11] == color.w()); - // Check 48 - 64 bytes - intensity - QVERIFY(floatData[12] == intensity); - QVERIFY(floatData[13] == 0.0f); - QVERIFY(floatData[14] == 0.0f); - QVERIFY(floatData[15] == 0.0f); -} - -void tst_QGraphicsUtils::fillMatrix4x4() -{ - // row major - QMatrix4x4 mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f); - - // column major - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(mat, 1, 16); - - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 1; - description.m_offset = 0; - description.m_arrayStride = 0; - description.m_matrixStride = 16; - - - QByteArray data(description.m_size * 16 * sizeof(GLfloat), 0); - char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); - // Check for no offset/no stride - for (int i = 0; i < 16; ++i) - QVERIFY((((GLfloat *)innerData)[i]) == matData[i]); - - description.m_offset = 12; - data = QByteArray((description.m_size * 16 + description.m_offset) * sizeof(GLfloat), 0); - innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); - // Check with 12 offset/no stride - for (int i = 0; i < 16; ++i) - QVERIFY((((GLfloat *)innerData)[3 + i]) == matData[i]); - - description.m_matrixStride = 16; - data = QByteArray((description.m_size * 16 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); - innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); - // Check with 10 offset/ 16 stride - int offset = description.m_offset / sizeof(GLfloat); - int matrixStride = description.m_matrixStride / sizeof(GLfloat); - - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 4; ++row) - QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); - offset += matrixStride; - } -} - -void tst_QGraphicsUtils::fillMatrix3x4() -{ - QMatrix3x4 mat; - - mat.fill(6.0f); - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); - - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 1; - description.m_offset = 16; - description.m_arrayStride = 0; - description.m_matrixStride = 12; - - QByteArray data((description.m_size * 12 + 3 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); - char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 3, 4); - // Check with 16 offset/ 12 stride - int offset = description.m_offset / sizeof(GLfloat); - int matrixStride = description.m_matrixStride / sizeof(GLfloat); - - for (int col = 0; col < 3; ++col) { - for (int row = 0; row < 4; ++row) - QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 4 + row]); - offset += matrixStride; - } -} - -void tst_QGraphicsUtils::fillMatrix4x3() -{ - QMatrix4x3 mat; - - mat.fill(6.0f); - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); - - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 1; - description.m_offset = 16; - description.m_arrayStride = 0; - description.m_matrixStride = 16; - - QByteArray data((description.m_size * 12 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); - char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); - // Check with 16 offset/ 16 stride - int offset = description.m_offset / sizeof(GLfloat); - int matrixStride = description.m_matrixStride / sizeof(GLfloat); - - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 3; ++row) - QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[col * 3 + row]); - offset += matrixStride; - } -} - -void tst_QGraphicsUtils::fillMatrixArray() -{ - QMatrix4x3 mat1; - QMatrix4x3 mat2; - QMatrix4x3 mat3; - mat1.fill(6.0f); - mat2.fill(2.0f); - mat3.fill(7.0f); - - QVariantList matrices = QVariantList() << QVariant::fromValue(mat1) << QVariant::fromValue(mat2) << QVariant::fromValue(mat3); - - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(matrices), 3, 12); - - Qt3DRender::Render::ShaderUniform description; - - description.m_size = 3; - description.m_offset = 12; - description.m_arrayStride = 4; - description.m_matrixStride = 16; - - QByteArray data((description.m_size * (12 + 4 * description.m_matrixStride + description.m_arrayStride) + description.m_offset) * sizeof(GLfloat), 0); - char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); - // Check with 12 offset/ 4 array stride / 16 matrix stride - int offset = description.m_offset / sizeof(GLfloat); - int matrixStride = description.m_matrixStride / sizeof(GLfloat); - int arrayStride = description.m_arrayStride / sizeof(GLfloat); - - for (int i = 0; i < 3; ++i) { - for (int col = 0; col < 4; ++col) { - for (int row = 0; row < 3; ++row) { - int idx = i * 4 * 3 + col * 3 + row; - QVERIFY((((GLfloat *)innerData)[offset + row]) == matData[idx]); - } - offset += matrixStride; - } - offset += arrayStride; - } -} - -QTEST_APPLESS_MAIN(tst_QGraphicsUtils) - -#include "tst_qgraphicsutils.moc" diff --git a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp index 1ff899936..daec0b86c 100644 --- a/tests/auto/render/raycastingjob/tst_raycastingjob.cpp +++ b/tests/auto/render/raycastingjob/tst_raycastingjob.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include diff --git a/tests/auto/render/render.pro b/tests/auto/render/render.pro index 2b73ec8b7..14fc74883 100644 --- a/tests/auto/render/render.pro +++ b/tests/auto/render/render.pro @@ -4,7 +4,6 @@ qtConfig(private_tests) { SUBDIRS += \ entity \ renderpass \ - qgraphicsutils \ shader \ shaderbuilder \ texture \ @@ -125,19 +124,8 @@ QT_FOR_CONFIG += 3drender-private qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) { SUBDIRS += \ - filtercompatibletechniquejob \ - graphicshelpergl3_3 \ - graphicshelpergl3_2 \ - graphicshelpergl2 \ - glshadermanager \ - materialparametergathererjob \ - textures \ - renderer \ - renderviewutils \ - renderviews \ - renderqueue \ - renderviewbuilder \ - gltexture + opengl \ + scene2d qtConfig(qt3d-extras) { SUBDIRS += \ @@ -158,8 +146,6 @@ qtConfig(qt3d-opengl-renderer):qtConfig(private_tests) { scene2d } - !macos: SUBDIRS += graphicshelpergl4 - qtConfig(qt3d-simd-avx2): SUBDIRS += alignedresourcesmanagers-avx qtConfig(qt3d-simd-sse2):!qtConfig(qt3d-simd-avx2): SUBDIRS += alignedresourcesmanagers-sse } diff --git a/tests/auto/render/renderer/renderer.pro b/tests/auto/render/renderer/renderer.pro deleted file mode 100644 index cbafc156b..000000000 --- a/tests/auto/render/renderer/renderer.pro +++ /dev/null @@ -1,9 +0,0 @@ -TEMPLATE = app - -TARGET = tst_renderer - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_renderer.cpp diff --git a/tests/auto/render/renderer/tst_renderer.cpp b/tests/auto/render/renderer/tst_renderer.cpp deleted file mode 100644 index 0cbc1aefc..000000000 --- a/tests/auto/render/renderer/tst_renderer.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class tst_Renderer : public QObject -{ - Q_OBJECT -public : - tst_Renderer() {} - ~tst_Renderer() {} - -private Q_SLOTS: - - void checkPreRenderBinJobs() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); - Qt3DRender::Render::RenderSettings settings; - // owned by FG manager - Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); - const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); - - nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); - settings.setActiveFrameGraphId(fgRootId); - - renderer.setNodeManagers(&nodeManagers); - renderer.setSettings(&settings); - renderer.setOffscreenSurfaceHelper(&offscreenHelper); - renderer.initialize(); - - // Ensure invoke calls are performed - QCoreApplication::processEvents(); - - // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) - QVector jobs = renderer.preRenderingJobs(); - - // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1); // RayCastingJob - - // WHEN - renderer.m_sendBufferCaptureJob->addRequest({Qt3DCore::QNodeId(), {}}); - jobs = renderer.preRenderingJobs(); - - // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob - 1); // SendBufferCaptureJob - // Note: pending render buffer captures are only cleared when the job is run - - // WHEN - renderer.m_updatedSetFences.push_back({Qt3DCore::QNodeId(), nullptr}); - jobs = renderer.preRenderingJobs(); - - // THEN - QCOMPARE(jobs.size(), - 1 + // PickBoundingVolumeJob - 1 + // RayCastingJob - 1 + // SendBufferCaptureJob - 1); // SendSetFenceHandlesJob - // Note: pending set fence handles are only cleared when the job is run - - // Properly shutdown command thread - renderer.shutdown(); - } - - void checkRenderBinJobs() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::RenderQueue *renderQueue = renderer.renderQueue(); - Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); - Qt3DRender::Render::RenderSettings settings; - // owned by FG manager - Qt3DRender::Render::ViewportNode *fgRoot = new Qt3DRender::Render::ViewportNode(); - const Qt3DCore::QNodeId fgRootId = Qt3DCore::QNodeId::createId(); - - nodeManagers.frameGraphManager()->appendNode(fgRootId, fgRoot); - settings.setActiveFrameGraphId(fgRootId); - - renderer.setNodeManagers(&nodeManagers); - renderer.setSettings(&settings); - renderer.setOffscreenSurfaceHelper(&offscreenHelper); - renderer.initialize(); - - // Ensure invoke calls are performed - QCoreApplication::processEvents(); - - // NOTE: FilterCompatibleTechniqueJob and ShaderGathererJob cannot run because the context - // is not initialized in this test - - const int renderViewBuilderMaterialCacheJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); - // syncMaterialGathererJob - // n * materialGathererJob - const int layerCacheJobCount = 2; - // filterEntityByLayerJob, - // syncFilterEntityByLayerJob - - const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); - - const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); - // RenderViewBuilder renderViewJob, - // syncRenderViewInitializationJob, - // syncFrustumCullingJob, - // filterProximityJob, - // setClearDrawBufferIndexJob, - // frustumCullingJob, - // syncRenderCommandUpdateJob, - // syncRenderViewCommandPostUpdateJob - // n * (RenderViewCommandBuildJobs) - - // WHEN - QVector jobs = renderer.renderBinJobs(); - - // THEN -> AllDirty - // (Renderer is not initialized so FilterCompatibleTechniqueJob - // and ShaderGathererJob are not added here) - QCOMPARE(jobs.size(), - 1 + // EntityEnabledDirty - 1 + // WorldTransformJob - 1 + // UpdateWorldBoundingVolume - 1 + // UpdateShaderDataTransform - 1 + // ExpandBoundingVolumeJob - 1 + // CalculateBoundingVolumeJob - 1 + // UpdateMeshTriangleListJob - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // BufferGathererJob - 1 + // TexturesGathererJob - 1 + // UpdateEntityLayersJob - 1 + // LightGathererJob - 1 + // CacheLightJob - 1 + // RenderableEntityFilterJob - 1 + // CacheRenderableEntitiesJob - 1 + // ComputableEntityFilterJob - 1 + // CacheComputableEntitiesJob - singleRenderViewJobCount + - singleRenderViewCommandRebuildJobCount + - layerCacheJobCount + - renderViewBuilderMaterialCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (Nothing in cache) - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - singleRenderViewJobCount + - singleRenderViewCommandRebuildJobCount + - renderViewBuilderMaterialCacheJobCount + - layerCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN (nothing dirty, no buffers, no layers to be rebuilt, no materials to be rebuilt) (RV leaf in cache) - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::FrameGraphDirty, nullptr); - renderer.cache()->leafNodeCache[renderer.m_frameGraphLeaves.first()] = {}; - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - singleRenderViewJobCount + - singleRenderViewCommandRebuildJobCount + - renderViewBuilderMaterialCacheJobCount + - layerCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::EntityEnabledDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // EntityEnabledDirty - singleRenderViewJobCount + - layerCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TransformDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // WorldTransformJob - 1 + // UpdateWorldBoundingVolume - 1 + // UpdateShaderDataTransform - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // ExpandBoundingVolumeJob - singleRenderViewJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::MaterialDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - singleRenderViewJobCount + - singleRenderViewCommandRebuildJobCount + - renderViewBuilderMaterialCacheJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::GeometryDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // CalculateBoundingVolumeJob - 1 + // UpdateMeshTriangleListJob - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // ExpandBoundingVolumeJob - 1 + // RenderableEntityFilterPtr - 1 + // SyncRenderableEntities - singleRenderViewCommandRebuildJobCount + - singleRenderViewJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::BuffersDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // updateSkinningPaletteJob - 1 + // SyncLoadingJobs - 1 + // CalculateBoundingVolumeJob - 1 + // UpdateMeshTriangleListJob - 1 + // BufferGathererJob - singleRenderViewJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // WHEN - renderer.markDirty(Qt3DRender::Render::AbstractRenderer::TexturesDirty, nullptr); - jobs = renderer.renderBinJobs(); - - // THEN (level - QCOMPARE(jobs.size(), - 1 + // updateLevelOfDetailJob - 1 + // cleanupJob - 1 + // VAOGatherer - 1 + // TexturesGathererJob - 1 + // updateSkinningPaletteJob - 1 + // SyncTexturesGathererJob - singleRenderViewJobCount); - - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - renderQueue->reset(); - - // Properly shutdown command thread - renderer.shutdown(); - } -}; - -QTEST_MAIN(tst_Renderer) - -#include "tst_renderer.moc" diff --git a/tests/auto/render/renderqueue/renderqueue.pro b/tests/auto/render/renderqueue/renderqueue.pro deleted file mode 100644 index 945fe4cf4..000000000 --- a/tests/auto/render/renderqueue/renderqueue.pro +++ /dev/null @@ -1,11 +0,0 @@ -TEMPLATE = app - -TARGET = tst_renderqueue - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_renderqueue.cpp - -include(../../core/common/common.pri) diff --git a/tests/auto/render/renderqueue/tst_renderqueue.cpp b/tests/auto/render/renderqueue/tst_renderqueue.cpp deleted file mode 100644 index 071f9b3a5..000000000 --- a/tests/auto/render/renderqueue/tst_renderqueue.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include - -class tst_RenderQueue : public QObject -{ - Q_OBJECT -public : - tst_RenderQueue() {} - ~tst_RenderQueue() {} - -private Q_SLOTS: - void setRenderViewCount(); - void circleQueues(); - void checkOrder(); - void checkTimeToSubmit(); - void concurrentQueueAccess(); - void resetQueue(); -}; - - -void tst_RenderQueue::setRenderViewCount() -{ - // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; - - // THEN - QCOMPARE(renderQueue.wasReset(), true); - - // WHEN - renderQueue.setTargetRenderViewCount(7); - - // THEN - QCOMPARE(renderQueue.wasReset(), false); - QVERIFY(renderQueue.targetRenderViewCount() == 7); - QVERIFY(renderQueue.currentRenderViewCount()== 0); -} - -void tst_RenderQueue::circleQueues() -{ - // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; - renderQueue.setTargetRenderViewCount(7); - - // WHEN - for (int j = 0; j < 10; j++) { - - // WHEN - renderQueue.reset(); - renderQueue.setTargetRenderViewCount(7); - - // THEN - QVERIFY(!renderQueue.isFrameQueueComplete()); - QCOMPARE(renderQueue.currentRenderViewCount(), 0); - - // WHEN - QList renderViews; - for (int i = 0; i < 7; i++) { - renderViews << new Qt3DRender::Render::RenderView(); - renderQueue.queueRenderView(renderViews.at(i), i); - } - - // THEN - QVERIFY(renderQueue.isFrameQueueComplete()); - } -} - -void tst_RenderQueue::checkOrder() -{ - // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; - renderQueue.setTargetRenderViewCount(7); - QVector renderViews(7); - - // WHEN - for (int i = 0; i < 7; ++i) { - int processingOrder = (i % 2 == 0) ? (6 - i) : i; - renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); - renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); - } - - // THEN - QVector frame = renderQueue.nextFrameQueue(); - for (int i = 0; i < 7; ++i) { - QVERIFY(frame[i] == renderViews[i]); - } -} - -void tst_RenderQueue::checkTimeToSubmit() -{ - // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; - renderQueue.setTargetRenderViewCount(7); - QVector renderViews(7); - - // WHEN - for (int i = 0; i < 7; i++) { - int processingOrder = (i % 2 == 0) ? (6 - i) : i; - renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); - renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); - - // THEN - if (i < 6) - QVERIFY(!renderQueue.isFrameQueueComplete()); - else - QVERIFY(renderQueue.isFrameQueueComplete()); - } -} - -class SimpleWorker : public QThread -{ - Q_OBJECT -public: - QSemaphore m_waitSubmit; - QSemaphore m_waitQueue; - Qt3DRender::Render::RenderQueue *m_renderQueues; - -public Q_SLOTS: - - void run() final // In Thread - { - for (int i = 0; i < 5; i++) { - m_waitQueue.acquire(); - - QVERIFY(m_renderQueues->currentRenderViewCount() == 0); - QVERIFY(!m_renderQueues->isFrameQueueComplete()); - - for (int j = 0; j < 7; ++j) { - // THEN - QCOMPARE(m_renderQueues->currentRenderViewCount(), j); - // WHEN - m_renderQueues->queueRenderView(new Qt3DRender::Render::RenderView(), j); - // THEN - QVERIFY(m_renderQueues->targetRenderViewCount() == 7); - QCOMPARE(m_renderQueues->currentRenderViewCount(), j + 1); - QVERIFY(m_renderQueues->isFrameQueueComplete() == (j == 6)); - QThread::msleep(20); // Simulates business - } - - QVERIFY(m_renderQueues->isFrameQueueComplete()); - m_waitSubmit.release(); - } - } -}; - - -void tst_RenderQueue::concurrentQueueAccess() -{ - // GIVEN - Qt3DRender::Render::RenderQueue *renderQueue = new Qt3DRender::Render::RenderQueue; - - SimpleWorker *jobsThread = new SimpleWorker(); - renderQueue->setTargetRenderViewCount(7); - jobsThread->m_renderQueues = renderQueue; - - // THEN - QVERIFY(jobsThread->m_renderQueues->targetRenderViewCount() == renderQueue->targetRenderViewCount()); - QVERIFY(jobsThread->m_renderQueues->currentRenderViewCount() == renderQueue->currentRenderViewCount()); - - // Start thread - jobsThread->start(); - - jobsThread->m_waitQueue.release(); - - for (int i = 0; i < 5; ++i) { - jobsThread->m_waitSubmit.acquire(); - - // WHEN unlocked - // THEN - QVERIFY (renderQueue->isFrameQueueComplete()); - QCOMPARE(renderQueue->nextFrameQueue().size(), renderQueue->targetRenderViewCount()); - - // reset queue for next frame - renderQueue->reset(); - renderQueue->setTargetRenderViewCount(7); - jobsThread->m_waitQueue.release(); - } - jobsThread->wait(); -} - -void tst_RenderQueue::resetQueue() -{ - // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; - - for (int j = 0; j < 5; j++) { - // WHEN - renderQueue.setTargetRenderViewCount(5); - // THEN - QCOMPARE(renderQueue.wasReset(), false); - QVERIFY(renderQueue.currentRenderViewCount() == 0); - - // WHEN - QVector renderViews(5); - for (int i = 0; i < 5; ++i) { - renderQueue.queueRenderView(renderViews.at(i), i); - } - // THEN - QCOMPARE(renderQueue.currentRenderViewCount(), 5); - QVERIFY(renderQueue.isFrameQueueComplete()); - - // WHEN - renderQueue.reset(); - QCOMPARE(renderQueue.wasReset(), true); - // THEN - QVERIFY(renderQueue.currentRenderViewCount() == 0); - } -} - -QTEST_APPLESS_MAIN(tst_RenderQueue) - -#include "tst_renderqueue.moc" diff --git a/tests/auto/render/renderviewbuilder/renderviewbuilder.pro b/tests/auto/render/renderviewbuilder/renderviewbuilder.pro deleted file mode 100644 index 00fdd49cf..000000000 --- a/tests/auto/render/renderviewbuilder/renderviewbuilder.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_renderviewbuilder - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_renderviewbuilder.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp deleted file mode 100644 index 6024084bd..000000000 --- a/tests/auto/render/renderviewbuilder/tst_renderviewbuilder.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Paul Lemire -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class TestAspect : public QRenderAspect -{ -public: - TestAspect(Qt3DCore::QNode *root) - : QRenderAspect(Qt3DRender::QRenderAspect::Synchronous) - , m_jobManager(new Qt3DCore::QAspectJobManager()) - { - Qt3DCore::QAbstractAspectPrivate::get(this)->m_jobManager = m_jobManager.data(); - QRenderAspect::onRegistered(); - - QVector nodes; - Qt3DCore::QNodeVisitor v; - v.traverse(root, [&nodes](Qt3DCore::QNode *node) { - Qt3DCore::QNodePrivate *d = Qt3DCore::QNodePrivate::get(node); - d->m_typeInfo = const_cast(Qt3DCore::QNodePrivate::findStaticMetaObject(node->metaObject())); - d->m_hasBackendNode = true; - nodes << node; - }); - - for (const auto node: nodes) - d_func()->createBackendNode({ - node->id(), - Qt3DCore::QNodePrivate::get(node)->m_typeInfo, - Qt3DCore::NodeTreeChange::Added, - node - }); - } - - ~TestAspect() - { - QRenderAspect::onUnregistered(); - } - - Qt3DRender::Render::NodeManagers *nodeManagers() const - { - return d_func()->m_renderer->nodeManagers(); - } - - Render::Renderer *renderer() const - { - return static_cast(d_func()->m_renderer); - } - - Render::MaterialParameterGathererJobPtr materialGathererJob() const - { - Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); - job->setNodeManagers(nodeManagers()); - return job; - } - - void onRegistered() { QRenderAspect::onRegistered(); } - void onUnregistered() { QRenderAspect::onUnregistered(); } - -private: - QScopedPointer m_jobManager; -}; - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -namespace { - -Qt3DCore::QEntity *buildSimpleScene(Qt3DRender::QFrameGraphNode *fg) -{ - Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); - - Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); - renderSettings->setActiveFrameGraph(fg); - root->addComponent(renderSettings); - - // Scene - { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); - Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DRender::QGeometryRenderer(); - e->addComponent(material); - e->addComponent(geometryRenderer); - e->setParent(root); - } - { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); - Qt3DRender::QComputeCommand *computeCommand = new Qt3DRender::QComputeCommand(); - e->addComponent(material); - e->addComponent(computeCommand); - e->setParent(root); - } - - { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(); - e->addComponent(light); - e->setParent(root); - } - - { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QSpotLight *light = new Qt3DRender::QSpotLight(); - e->addComponent(light); - e->setParent(root); - } - - { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QEnvironmentLight *light = new Qt3DRender::QEnvironmentLight(); - e->addComponent(light); - e->setParent(root); - } - - return root; -} - -Qt3DCore::QEntity *buildEntityFilterTestScene(Qt3DRender::QFrameGraphNode *fg, Qt3DRender::QLayer *layer) -{ - Qt3DCore::QEntity *root = new Qt3DCore::QEntity(); - - Qt3DRender::QRenderSettings* renderSettings = new Qt3DRender::QRenderSettings(); - renderSettings->setActiveFrameGraph(fg); - root->addComponent(renderSettings); - - // Scene - for (int i = 0; i < 200; ++i) { - Qt3DCore::QEntity *e = new Qt3DCore::QEntity(); - Qt3DRender::QMaterial *material = new Qt3DRender::QMaterial(); - Qt3DRender::QGeometryRenderer *geometryRenderer = new Qt3DRender::QGeometryRenderer(); - e->addComponent(material); - e->addComponent(geometryRenderer); - if (i % 2 == 0) - e->addComponent(layer); - e->setParent(root); - } - - return root; -} - -} // anonymous - - -class tst_RenderViewBuilder : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - - void checkInitialState() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - - // THEN - QCOMPARE(renderViewBuilder.renderViewIndex(), 0); - QCOMPARE(renderViewBuilder.renderer(), testAspect.renderer()); - QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), false); - QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), false); - QVERIFY(!renderViewBuilder.renderViewJob().isNull()); - QVERIFY(!renderViewBuilder.frustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.syncPreFrustumCullingJob().isNull()); - QVERIFY(!renderViewBuilder.setClearDrawBufferIndexJob().isNull()); - - QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); - QVERIFY(renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); - - QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), 0); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); - - // WHEN - renderViewBuilder.prepareJobs(); - - // THEN - QVERIFY(!renderViewBuilder.syncRenderViewPreCommandUpdateJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewPostCommandUpdateJob().isNull()); - QVERIFY(!renderViewBuilder.syncRenderViewPostInitializationJob().isNull()); - QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - - QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - - // THEN - QCOMPARE(renderViewBuilder.layerCacheNeedsToBeRebuilt(), true); - QVERIFY(!renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - - // mark jobs dirty and recheck - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - - // THEN - QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), true); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - QVERIFY(!renderViewBuilder.syncMaterialGathererJob().isNull()); - - // mark jobs dirty and recheck - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); - } - } - - void checkCheckJobDependencies() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - // THEN - // Step 1 - QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update - - - // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.renderViewJob().data()); - - // Step 3 - QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); - QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - - QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewPostInitializationJob().data()); - - QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); - - // Step 4 - QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - - QCOMPARE(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().size(), renderViewBuilder.materialGathererJobs().size() + 7); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->cacheLightJob())); - - // Step 5 - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); - } - - // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); - } - } - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); - renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - // THEN - // Step 1 - QCOMPARE(renderViewBuilder.renderViewJob()->dependencies().size(), 1); // Depends upon skinning palette update - - // Step 2 - QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.syncRenderViewPostInitializationJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.renderViewJob().data()); - - // Step 3 - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateEntityLayersJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterEntityByLayerJob()->dependencies().contains(testAspect.renderer()->updateTreeEnabledJob())); - - QCOMPARE(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().size(), 1); - QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob()->dependencies().contains(renderViewBuilder.filterEntityByLayerJob())); - - QCOMPARE(renderViewBuilder.filterProximityJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.filterProximityJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().size(), 1); - QCOMPARE(renderViewBuilder.setClearDrawBufferIndexJob()->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewPostInitializationJob().data()); - - QCOMPARE(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().size(), 3); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateWorldTransformJob())); - QVERIFY(renderViewBuilder.syncPreFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob())); - - for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { - QCOMPARE(materialGatherer->dependencies().size(), 3); - QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob())); - QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob())); - } - - // Step 4 - QCOMPARE(renderViewBuilder.frustumCullingJob()->dependencies().size(), 2); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(renderViewBuilder.syncPreFrustumCullingJob())); - QVERIFY(renderViewBuilder.frustumCullingJob()->dependencies().contains(testAspect.renderer()->expandBoundingVolumeJob())); - - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncRenderViewPostInitializationJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.syncFilterEntityByLayerJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.frustumCullingJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(renderViewBuilder.filterProximityJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob())); - QVERIFY(renderViewBuilder.syncRenderViewPreCommandUpdateJob()->dependencies().contains(testAspect.renderer()->textureGathererJob())); - - // Step 5 - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { - QCOMPARE(renderViewBuilderJob->dependencies().size(), 1); - QCOMPARE(renderViewBuilderJob->dependencies().constFirst().toStrongRef().data(), - renderViewBuilder.syncRenderViewPreCommandUpdateJob().data()); - } - - // Step 6 - QCOMPARE(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().size(), renderViewBuilder.renderViewCommandUpdaterJobs().size()); - for (const auto &renderViewBuilderJob : renderViewBuilder.renderViewCommandUpdaterJobs()) { - QVERIFY(renderViewBuilder.syncRenderViewPostCommandUpdateJob()->dependencies().contains(renderViewBuilderJob)); - } - } - } - - void checkRenderViewJobExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - renderViewBuilder.renderViewJob()->run(); - - // THEN - QVERIFY(renderViewBuilder.renderViewJob()->renderView() != nullptr); - } - - void checkLightGatherExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - renderer->lightGathererJob()->run(); - - // THEN - QCOMPARE(renderer->lightGathererJob()->lights().size(), 2); - QVERIFY(renderer->lightGathererJob()->takeEnvironmentLight() != nullptr); - } - - void checkRenderableEntitiesFilteringExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - renderer->renderableEntityFilterJob()->run(); - - // THEN - QCOMPARE(renderer->renderableEntityFilterJob()->filteredEntities().size(), 1); - } - - void checkComputableEntitiesFilteringExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - renderer->computableEntityFilterJob()->run(); - - // THEN - QCOMPARE(renderer->computableEntityFilterJob()->filteredEntities().size(), 1); - } - - void checkSyncRenderViewInitializationExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(clearBuffer); - Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(layerFilter); - Qt3DRender::QTechniqueFilter *techniqueFilter = new Qt3DRender::QTechniqueFilter(frustumCulling); - Qt3DRender::QRenderPassFilter *renderPassFilter = new Qt3DRender::QRenderPassFilter(techniqueFilter); - Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); - - layerFilter->addLayer(layer); - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(renderPassFilter->id()); - QVERIFY(leafNode != nullptr); - - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); - for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() == nullptr); - QVERIFY(materialGatherer->renderPassFilter() == nullptr); - } - - // WHEN - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewPostInitializationJob()->run(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); - for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() != nullptr); - QVERIFY(materialGatherer->renderPassFilter() != nullptr); - } - } - { - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), false); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 0); - for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() == nullptr); - QVERIFY(materialGatherer->renderPassFilter() == nullptr); - } - - // WHEN - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewPostInitializationJob()->run(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->isActive(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->hasLayerFilter(), true); - QCOMPARE(renderViewBuilder.filterEntityByLayerJob()->layerFilters().size(), 1); - for (const auto &materialGatherer : renderViewBuilder.materialGathererJobs()) { - QVERIFY(materialGatherer->techniqueFilter() != nullptr); - QVERIFY(materialGatherer->renderPassFilter() != nullptr); - } - } - } - - void checkSyncFrustumCullingExecution() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::QFrustumCulling *frustumCulling = new Qt3DRender::QFrustumCulling(clearBuffer); - Qt3DRender::QCameraSelector *cameraSelector = new Qt3DRender::QCameraSelector(frustumCulling); - Qt3DRender::QCamera *camera = new Qt3DRender::QCamera(); - cameraSelector->setCamera(camera); - - Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(cameraSelector->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - // THEN - QCOMPARE(renderViewBuilder.frustumCullingJob()->viewProjection(), Matrix4x4()); - - // WHEN - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncPreFrustumCullingJob()->run(); - - // THEN - QCOMPARE(convertToQMatrix4x4(renderViewBuilder.frustumCullingJob()->viewProjection()), camera->projectionMatrix() * camera->viewMatrix()); - } - - void checkRemoveEntitiesNotInSubset() - { - // GIVEN - Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); - Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); - Qt3DRender::QLayerFilter *layerFilter = new Qt3DRender::QLayerFilter(clearBuffer); - Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); - layerFilter->addLayer(layer); - Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); - - // THEN - Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id()); - QVERIFY(leafNode != nullptr); - - // WHEN - renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); - - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); - renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); - renderViewBuilder.prepareJobs(); - renderViewBuilder.buildJobHierachy(); - - renderer->renderableEntityFilterJob()->run(); - renderer->cacheRenderableEntitiesJob()->run(); - - renderViewBuilder.renderViewJob()->run(); - renderViewBuilder.syncRenderViewPostInitializationJob()->run(); - renderViewBuilder.filterEntityByLayerJob()->run(); - - QVector renderableEntity = renderer->renderableEntityFilterJob()->filteredEntities(); - QVector filteredEntity = renderViewBuilder.filterEntityByLayerJob()->filteredEntities(); - - // THEN - QCOMPARE(renderableEntity.size(), 200); - QCOMPARE(filteredEntity.size(), 100); - - std::sort(renderableEntity.begin(), renderableEntity.end()); - - // WHEN - renderableEntity = Qt3DRender::Render::RenderViewBuilder::entitiesInSubset(renderableEntity, filteredEntity); - - // THEN - QCOMPARE(renderableEntity.size(), 100); - for (const auto entity : renderableEntity) { - QVERIFY(filteredEntity.contains(entity)); - } - } - -}; - -QTEST_MAIN(tst_RenderViewBuilder) - -#include "tst_renderviewbuilder.moc" diff --git a/tests/auto/render/renderviews/renderviews.pro b/tests/auto/render/renderviews/renderviews.pro deleted file mode 100644 index 046c00696..000000000 --- a/tests/auto/render/renderviews/renderviews.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_renderviews - -QT += 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_renderviews.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/renderviews/tst_renderviews.cpp b/tests/auto/render/renderviews/tst_renderviews.cpp deleted file mode 100644 index b434fe83a..000000000 --- a/tests/auto/render/renderviews/tst_renderviews.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -namespace { - -void compareShaderParameterPacks(const ShaderParameterPack &t1, - const ShaderParameterPack &t2) -{ - const PackUniformHash hash1 = t1.uniforms(); - const PackUniformHash hash2 = t2.uniforms(); - - QCOMPARE(hash1.keys.size(), hash2.keys.size()); - - for (int i = 0, m = hash1.keys.size(); i < m; ++i) { - const int key = hash1.keys.at(i); - QCOMPARE(hash1.value(key), hash2.value(key)); - } -} - -} // anonymous - -class tst_RenderViews : public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT - -private Q_SLOTS: - - void checkRenderViewSizeFitsWithAllocator() - { - QSKIP("Allocated Disabled"); - QVERIFY(sizeof(RenderView) <= 192); - QVERIFY(sizeof(RenderView::InnerData) <= 192); - } - - void checkRenderViewInitialState() - { - // GIVEN - RenderView renderView; - - // THEN - QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); - } - - void checkMemoryBarrierInitialization() - { - // GIVEN - RenderView renderView; - - // THEN - QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); - - // WHEN - const QMemoryBarrier::Operations barriers(QMemoryBarrier::BufferUpdate|QMemoryBarrier::ShaderImageAccess); - renderView.setMemoryBarrier(barriers); - - // THEN - QCOMPARE(renderView.memoryBarrier(), barriers); - } - - void checkSetRenderViewConfig() - { - TestRenderer renderer; - { - // GIVEN - const QMemoryBarrier::Operations barriers(QMemoryBarrier::AtomicCounter|QMemoryBarrier::ShaderStorage); - Qt3DRender::QMemoryBarrier frontendBarrier; - FrameGraphManager frameGraphManager; - MemoryBarrier backendBarrier; - RenderView renderView; - // setRenderViewConfigFromFrameGraphLeafNode assumes node has a manager - backendBarrier.setFrameGraphManager(&frameGraphManager); - backendBarrier.setRenderer(&renderer); - - // WHEN - frontendBarrier.setWaitOperations(barriers); - simulateInitializationSync(&frontendBarrier, &backendBarrier); - - // THEN - QCOMPARE(renderView.memoryBarrier(), QMemoryBarrier::None); - QCOMPARE(backendBarrier.waitOperations(), barriers); - - // WHEN - Qt3DRender::Render::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); - - // THEN - QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); - } - // TO DO: Complete tests for other framegraph node types - } - - void checkRenderCommandBackToFrontSorting() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - RenderView renderView; - QVector rawCommands; - QVector sortTypes; - - renderer.setNodeManagers(&nodeManagers); - renderView.setRenderer(&renderer); - - sortTypes.push_back(QSortPolicy::BackToFront); - - for (int i = 0; i < 200; ++i) { - RenderCommand c; - c.m_depth = float(i); - rawCommands.push_back(c); - } - - // WHEN - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_depth > sortedCommands.at(j).m_depth); - - // RenderCommands are deleted by RenderView dtor - renderer.shutdown(); - } - - void checkRenderCommandMaterialSorting() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - RenderView renderView; - QVector rawCommands; - QVector sortTypes; - - renderer.setNodeManagers(&nodeManagers); - renderView.setRenderer(&renderer); - - sortTypes.push_back(QSortPolicy::Material); - - GLShader *dnas[5] = { - reinterpret_cast(0x250), - reinterpret_cast(0x500), - reinterpret_cast(0x1000), - reinterpret_cast(0x1500), - reinterpret_cast(0x2000) - }; - - for (int i = 0; i < 20; ++i) { - RenderCommand c; - c.m_glShader = dnas[i % 5]; - rawCommands.push_back(c); - } - - // WHEN - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - GLShader *targetShader; - - for (int j = 0; j < sortedCommands.size(); ++j) { - - if (j % 4 == 0) { - targetShader = sortedCommands.at(j).m_glShader; - if (j > 0) - QVERIFY(targetShader != sortedCommands.at(j - 1).m_glShader); - } - QCOMPARE(targetShader, sortedCommands.at(j).m_glShader); - } - - // RenderCommands are deleted by RenderView dtor - renderer.shutdown(); - } - - void checkRenderViewUniformMinification_data() - { - QTest::addColumn>("shaders"); - QTest::addColumn>("rawParameters"); - QTest::addColumn>("expectedMinimizedParameters"); - - Qt3DCore::QNodeId fakeTextureNodeId = Qt3DCore::QNodeId::createId(); - - ShaderParameterPack pack1; - pack1.setUniform(1, UniformValue(883)); - pack1.setUniform(2, UniformValue(1584.0f)); - pack1.setTexture(3, 0, fakeTextureNodeId); - - QShaderProgram *shader1 = new QShaderProgram(); - QShaderProgram *shader2 = new QShaderProgram(); - - shader1->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("1")); - shader2->setShaderCode(QShaderProgram::Vertex, QByteArrayLiteral("2")); - - ShaderParameterPack minifiedPack1; - - QTest::newRow("NoMinification") - << (QVector() << shader1 << shader2) - << (QVector() << pack1 << pack1) - << (QVector() << pack1 << pack1); - - QTest::newRow("SingleShaderMinified") - << (QVector() << shader1 << shader1 << shader1) - << (QVector() << pack1 << pack1 << pack1) - << (QVector() << pack1 << minifiedPack1 << minifiedPack1); - - QTest::newRow("MultipleShadersMinified") - << (QVector() << shader1 << shader1 << shader1 << shader2 << shader2 << shader2) - << (QVector() << pack1 << pack1 << pack1 << pack1 << pack1 << pack1) - << (QVector() << pack1 << minifiedPack1 << minifiedPack1 << pack1 << minifiedPack1 << minifiedPack1); - } - - void checkRenderViewUniformMinification() - { - QFETCH(QVector, shaders); - QFETCH(QVector, rawParameters); - QFETCH(QVector, expectedMinimizedParameters); - - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - renderer.setNodeManagers(&nodeManagers); - - GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager(); - for (int i = 0, m = shaders.size(); i < m; ++i) { - Shader* backend = new Shader(); - backend->setRenderer(&renderer); - simulateInitializationSync(shaders.at(i), backend); - shaderManager->createOrAdoptExisting(backend); - } - - RenderView renderView; - QVector rawCommands; - renderView.setRenderer(&renderer); - - for (int i = 0, m = shaders.size(); i < m; ++i) { - RenderCommand c; - c.m_shaderId = shaders.at(i)->id(); - c.m_glShader = shaderManager->lookupResource(c.m_shaderId); - c.m_parameterPack = rawParameters.at(i); - rawCommands.push_back(c); - } - - // WHEN - renderView.setCommands(rawCommands); - renderView.addSortType((QVector() << QSortPolicy::Uniform)); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands, sortedCommands); - - for (int i = 0, m = shaders.size(); i < m; ++i) { - const RenderCommand c = sortedCommands.at(i); - QCOMPARE(c.m_shaderId, shaders.at(i)->id()); - compareShaderParameterPacks(c.m_parameterPack, expectedMinimizedParameters.at(i)); - } - - renderer.shutdown(); - } - - - void checkRenderCommandFrontToBackSorting() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - RenderView renderView; - QVector rawCommands; - QVector sortTypes; - - renderer.setNodeManagers(&nodeManagers); - renderView.setRenderer(&renderer); - - sortTypes.push_back(QSortPolicy::FrontToBack); - - for (int i = 0; i < 200; ++i) { - RenderCommand c; - c.m_depth = float(i); - rawCommands.push_back(c); - } - - // WHEN - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_depth < sortedCommands.at(j).m_depth); - - // RenderCommands are deleted by RenderView dtor - renderer.shutdown(); - } - - void checkRenderCommandStateCostSorting() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - RenderView renderView; - QVector rawCommands; - QVector sortTypes; - - renderer.setNodeManagers(&nodeManagers); - renderView.setRenderer(&renderer); - - sortTypes.push_back(QSortPolicy::StateChangeCost); - - for (int i = 0; i < 200; ++i) { - RenderCommand c; - c.m_changeCost = i; - rawCommands.push_back(c); - } - - // WHEN - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - for (int j = 1; j < sortedCommands.size(); ++j) - QVERIFY(sortedCommands.at(j - 1).m_changeCost > sortedCommands.at(j).m_changeCost); - - // RenderCommands are deleted by RenderView dtor - renderer.shutdown(); - } - - void checkRenderCommandCombinedStateMaterialDepthSorting() - { - // GIVEN - Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - RenderView renderView; - QVector rawCommands; - QVector sortTypes; - - renderer.setNodeManagers(&nodeManagers); - renderView.setRenderer(&renderer); - - sortTypes.push_back(QSortPolicy::StateChangeCost); - sortTypes.push_back(QSortPolicy::Material); - sortTypes.push_back(QSortPolicy::BackToFront); - - GLShader *dna[5] = { - reinterpret_cast(0x250), - reinterpret_cast(0x500), - reinterpret_cast(0x1000), - reinterpret_cast(0x1500), - reinterpret_cast(0x2000) - }; - - float depth[3] = { - 10.0f, - 25.0f, - 30.0f - }; - - int stateChangeCost[2] = { - 100, - 200 - }; - - auto buildRC = [] (GLShader *dna, float depth, int changeCost) { - RenderCommand c; - c.m_glShader = dna; - c.m_depth = depth; - c.m_changeCost = changeCost; - return c; - }; - - RenderCommand c5 = buildRC(dna[3], depth[1], stateChangeCost[1]); - RenderCommand c3 = buildRC(dna[3], depth[0], stateChangeCost[1]); - RenderCommand c4 = buildRC(dna[2], depth[1], stateChangeCost[1]); - RenderCommand c8 = buildRC(dna[1], depth[1], stateChangeCost[1]); - RenderCommand c0 = buildRC(dna[0], depth[2], stateChangeCost[1]); - - RenderCommand c2 = buildRC(dna[2], depth[2], stateChangeCost[0]); - RenderCommand c9 = buildRC(dna[2], depth[0], stateChangeCost[0]); - RenderCommand c1 = buildRC(dna[1], depth[0], stateChangeCost[0]); - RenderCommand c7 = buildRC(dna[0], depth[2], stateChangeCost[0]); - RenderCommand c6 = buildRC(dna[0], depth[1], stateChangeCost[0]); - - rawCommands << c0 << c1 << c2 << c3 << c4 << c5 << c6 << c7 << c8 << c9; - - // WHEN - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - - // Ordered by higher state, higher shaderDNA and higher depth - QCOMPARE(c0, sortedCommands.at(4)); - QCOMPARE(c3, sortedCommands.at(1)); - QCOMPARE(c4, sortedCommands.at(2)); - QCOMPARE(c5, sortedCommands.at(0)); - QCOMPARE(c8, sortedCommands.at(3)); - - QCOMPARE(c1, sortedCommands.at(7)); - QCOMPARE(c2, sortedCommands.at(5)); - QCOMPARE(c6, sortedCommands.at(9)); - QCOMPARE(c7, sortedCommands.at(8)); - QCOMPARE(c9, sortedCommands.at(6)); - - // RenderCommands are deleted by RenderView dtor - renderer.shutdown(); - } - - void checkRenderCommandTextureSorting() - { - // GIVEN - RenderView renderView; - QVector sortTypes; - - sortTypes.push_back(QSortPolicy::Texture); - - - Qt3DCore::QNodeId tex1 = Qt3DCore::QNodeId::createId(); - Qt3DCore::QNodeId tex2 = Qt3DCore::QNodeId::createId(); - Qt3DCore::QNodeId tex3 = Qt3DCore::QNodeId::createId(); - Qt3DCore::QNodeId tex4 = Qt3DCore::QNodeId::createId(); - - RenderCommand a; - { - ShaderParameterPack pack; - pack.setTexture(0, 0, tex1); - pack.setTexture(1, 0, tex3); - pack.setTexture(2, 0, tex4); - pack.setTexture(3, 0, tex2); - a.m_parameterPack = pack; - } - RenderCommand b; - RenderCommand c; - { - ShaderParameterPack pack; - pack.setTexture(0, 0, tex1); - pack.setTexture(3, 0, tex2); - c.m_parameterPack = pack; - } - RenderCommand d; - { - ShaderParameterPack pack; - pack.setTexture(1, 0, tex3); - pack.setTexture(2, 0, tex4); - d.m_parameterPack = pack; - } - RenderCommand e; - { - ShaderParameterPack pack; - pack.setTexture(3, 0, tex2); - e.m_parameterPack = pack; - } - RenderCommand f; - { - ShaderParameterPack pack; - pack.setTexture(3, 0, tex2); - f.m_parameterPack = pack; - } - RenderCommand g; - { - ShaderParameterPack pack; - pack.setTexture(0, 0, tex1); - pack.setTexture(1, 0, tex3); - pack.setTexture(2, 0, tex4); - pack.setTexture(3, 0, tex2); - g.m_parameterPack = pack; - } - - // WHEN - QVector rawCommands = {a, b, c, d, e, f, g}; - renderView.addSortType(sortTypes); - renderView.setCommands(rawCommands); - renderView.sort(); - - // THEN - const QVector sortedCommands = renderView.commands(); - QCOMPARE(rawCommands.size(), sortedCommands.size()); - QCOMPARE(sortedCommands.at(0), a); - QCOMPARE(sortedCommands.at(1), g); - QCOMPARE(sortedCommands.at(2), d); - QCOMPARE(sortedCommands.at(3), c); - QCOMPARE(sortedCommands.at(4), e); - QCOMPARE(sortedCommands.at(5), f); - QCOMPARE(sortedCommands.at(6), b); - // RenderCommands are deleted by RenderView dtor - } -private: -}; - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -//APPLESS_ -QTEST_MAIN(Qt3DRender::Render::tst_RenderViews) - -#include "tst_renderviews.moc" diff --git a/tests/auto/render/renderviewutils/renderviewutils.pro b/tests/auto/render/renderviewutils/renderviewutils.pro deleted file mode 100644 index 90d8a2562..000000000 --- a/tests/auto/render/renderviewutils/renderviewutils.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_renderviewutils - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_renderviewutils.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/renderviewutils/tst_renderviewutils.cpp deleted file mode 100644 index 6d349f994..000000000 --- a/tests/auto/render/renderviewutils/tst_renderviewutils.cpp +++ /dev/null @@ -1,800 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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 -#include -#include -#include -#include -#include -#include -#include -#include "testrenderer.h" -#include "testpostmanarbiter.h" - -class tst_RenderViewUtils : public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT -private Q_SLOTS: - void topLevelScalarValueNoUniforms(); - void topLevelScalarValue(); - void topLevelTextureValueNoUniforms(); - void topLevelTextureValue(); - void topLevelArrayValue(); - void nestedShaderDataValue(); - void topLevelStructValue_data(); - void topLevelStructValue(); - void topLevelDynamicProperties(); - void transformedProperties(); - void shouldNotifyDynamicPropertyChanges(); - -private: - void initBackendShaderData(Qt3DRender::Render::AbstractRenderer *renderer, - Qt3DRender::QShaderData *frontend, - Qt3DRender::Render::ShaderDataManager *manager) - { - // Create children first - for (QObject *c : frontend->children()) { - Qt3DRender::QShaderData *cShaderData = qobject_cast(c); - if (cShaderData) - initBackendShaderData(renderer, cShaderData, manager); - } - - // Create backend element for frontend one - Qt3DRender::Render::ShaderData *backend = manager->getOrCreateResource(frontend->id()); - // Init the backend element - backend->setRenderer(renderer); - simulateInitializationSync(frontend, backend); - } - - void initBackendTexture(Qt3DRender::QAbstractTexture *frontend, - Qt3DRender::Render::TextureManager *manager) - { - // Create backend element for frontend one - Qt3DRender::Render::Texture *backend = manager->getOrCreateResource(frontend->id()); - // Init the backend element - simulateInitialization(frontend, backend); - } -}; - -class ScalarShaderData : public Qt3DRender::QShaderData -{ - Q_OBJECT - Q_PROPERTY(float scalar READ scalar WRITE setScalar NOTIFY scalarChanged) - -public: - ScalarShaderData(Qt3DCore::QNode *parent = nullptr) - : Qt3DRender::QShaderData(parent) - , m_scalar(0.0f) - { - } - - void setScalar(float scalar) - { - if (scalar != m_scalar) { - m_scalar = scalar; - emit scalarChanged(); - } - } - - float scalar() const - { - return m_scalar; - } - - QHash buildUniformMap(const QString &blockName) - { - QHash uniforms; - - uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); - - return uniforms; - } - -Q_SIGNALS: - void scalarChanged(); - -private: - float m_scalar; -}; - -class TextureShaderData : public Qt3DRender::QShaderData -{ - Q_OBJECT - Q_PROPERTY(Qt3DRender::QAbstractTexture* texture READ texture WRITE setTexture NOTIFY textureChanged) - -public: - TextureShaderData() - : Qt3DRender::QShaderData() - , m_texture(nullptr) - { - } - - void setTexture(Qt3DRender::QAbstractTexture *texture) - { - if (texture != m_texture) { - m_texture = texture; - emit textureChanged(); - } - } - - Qt3DRender::QAbstractTexture *texture() const - { - return m_texture; - } - - QHash buildUniformMap(const QString &blockName) - { - QHash uniforms; - - uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::ShaderUniform()); - - return uniforms; - } - -Q_SIGNALS: - void textureChanged(); - -private: - Qt3DRender::QAbstractTexture *m_texture; -}; - - -class ArrayShaderData : public Qt3DRender::QShaderData -{ - Q_OBJECT - Q_PROPERTY(QVariantList array READ array WRITE setArray NOTIFY arrayChanged) - -public: - ArrayShaderData() - : Qt3DRender::QShaderData() - { - } - - void setArray(const QVariantList &array) - { - if (array != m_array) { - m_array = array; - emit arrayChanged(); - } - } - - QVariantList array() const - { - return m_array; - } - - QHash buildUniformMap(const QString &blockName) - { - QHash uniforms; - - uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); - - return uniforms; - } - -Q_SIGNALS: - void arrayChanged(); - -private: - QVariantList m_array; -}; - -class StructShaderData : public Qt3DRender::QShaderData -{ - Q_OBJECT - Q_PROPERTY(float scalar READ scalar WRITE setScalar NOTIFY scalarChanged) - Q_PROPERTY(QVariantList array READ array WRITE setArray NOTIFY arrayChanged) - -public: - StructShaderData() - : Qt3DRender::QShaderData() - , m_scalar(0.0f) - { - } - - void setScalar(float scalar) - { - if (scalar != m_scalar) { - m_scalar = scalar; - emit scalarChanged(); - } - } - - float scalar() const - { - return m_scalar; - } - - void setArray(const QVariantList &array) - { - if (array != m_array) { - m_array = array; - emit arrayChanged(); - } - } - - QVariantList array() const - { - return m_array; - } - - virtual QHash buildUniformMap(const QString &blockName) - { - QHash uniforms; - - uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); - uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); - - return uniforms; - } - - virtual QHash buildUniformMapValues(const QString &blockName) - { - QHash uniforms; - - uniforms.insert(blockName + QStringLiteral(".scalar"), QVariant(scalar())); - uniforms.insert(blockName + QStringLiteral(".array[0]"), QVariant(array())); - - return uniforms; - } - -Q_SIGNALS: - void scalarChanged(); - void arrayChanged(); - -private: - float m_scalar; - QVariantList m_array; -}; - -class MultiLevelStructShaderData : public StructShaderData -{ - Q_OBJECT - Q_PROPERTY(Qt3DRender::QShaderData *inner READ inner WRITE setInner NOTIFY innerChanged) - -public: - MultiLevelStructShaderData() - : StructShaderData() - , m_inner(nullptr) - { - } - - void setInner(Qt3DRender::QShaderData *inner) - { - if (inner != m_inner) { - m_inner = inner; - emit innerChanged(); - } - } - - Qt3DRender::QShaderData *inner() const - { - return m_inner; - } - - QHash buildUniformMap(const QString &blockName) override - { - QHash innerUniforms; - - StructShaderData *innerData = nullptr; - if ((innerData = qobject_cast(m_inner)) != nullptr) - innerUniforms = innerData->buildUniformMap(QStringLiteral(".inner")); - - QHash uniforms = StructShaderData::buildUniformMap(blockName); - QHash::const_iterator it = innerUniforms.begin(); - const QHash::const_iterator end = innerUniforms.end(); - - while (it != end) { - uniforms.insert(blockName + it.key(), it.value()); - ++it; - } - return uniforms; - } - - QHash buildUniformMapValues(const QString &blockName) override - { - QHash innerUniformsValues; - - StructShaderData *innerData = nullptr; - if ((innerData = qobject_cast(m_inner)) != nullptr) - innerUniformsValues = innerData->buildUniformMapValues(QStringLiteral(".inner")); - - QHash uniformsValues = StructShaderData::buildUniformMapValues(blockName); - QHash::const_iterator it = innerUniformsValues.begin(); - const QHash::const_iterator end = innerUniformsValues.end(); - - while (it != end) { - uniformsValues.insert(blockName + it.key(), it.value()); - ++it; - } - - return uniformsValues; - } - -Q_SIGNALS: - void innerChanged(); - -private: - Qt3DRender::QShaderData *m_inner; -}; - -void tst_RenderViewUtils::topLevelScalarValueNoUniforms() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new ScalarShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - shaderData->setScalar(883.0f); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEB - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); - - // THEN - // activeUniformNamesToValue should be empty as blockBuilder.uniforms is - QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); -} - -void tst_RenderViewUtils::topLevelScalarValue() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new ScalarShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - shaderData->setScalar(883.0f); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); - - // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); - - while (it != end) { - // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - QCOMPARE(it.value(), QVariant(shaderData->scalar())); - ++it; - } -} - -void tst_RenderViewUtils::topLevelTextureValueNoUniforms() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new TextureShaderData); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager); - QScopedPointer texture(new Qt3DRender::QTexture2D); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - shaderData->setTexture(texture.data()); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEB - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("")); - - // THEN - // activeUniformNamesToValue should be empty as blockBuilder.uniforms is - QVERIFY(blockBuilder.activeUniformNamesToValue.isEmpty()); -} - -void tst_RenderViewUtils::topLevelTextureValue() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new TextureShaderData); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager); - QScopedPointer texture(new Qt3DRender::QTexture2D); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - initBackendTexture(texture.data(), textureManager.data()); - shaderData->setTexture(texture.data()); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); - - // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); - - while (it != end) { - // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - QCOMPARE(it.value(), QVariant::fromValue(shaderData->texture()->id())); - ++it; - } -} - -void tst_RenderViewUtils::topLevelArrayValue() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new ArrayShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; - shaderData->setArray(arrayValues); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(QStringLiteral("MyBlock")); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); - - // THEN - QVERIFY(blockBuilder.uniforms.count() == 1); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); - - while (it != end) { - // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - QCOMPARE(it.value(), QVariant(arrayValues)); - ++it; - } -} - -void tst_RenderViewUtils::nestedShaderDataValue() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer arrayShaderData(new ArrayShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - QScopedPointer shaderData1(new ScalarShaderData(arrayShaderData.data())); - QScopedPointer shaderData2(new ScalarShaderData(arrayShaderData.data())); - QScopedPointer shaderData3(new ScalarShaderData(arrayShaderData.data())); - - shaderData1->setScalar(883.0f); - shaderData2->setScalar(1200.0f); - shaderData3->setScalar(1340.0f); - QHash scalarValues; - scalarValues[QStringLiteral("MyBlock.array[0].scalar")] = shaderData1->scalar(); - scalarValues[QStringLiteral("MyBlock.array[1].scalar")] = shaderData2->scalar(); - scalarValues[QStringLiteral("MyBlock.array[2].scalar")] = shaderData3->scalar(); - - - const Qt3DCore::QNodeId id1 = shaderData1->id(); - const Qt3DCore::QNodeId id2 = shaderData2->id(); - const Qt3DCore::QNodeId id3 = shaderData3->id(); - - // WHEN - const QVariantList arrayValues = QVariantList() << QVariant::fromValue(id1) << QVariant::fromValue(id2) << QVariant::fromValue(id3); - arrayShaderData->setArray(arrayValues); - initBackendShaderData(&renderer, arrayShaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendArrayShaderData = manager->lookupResource(arrayShaderData->id()); - Qt3DRender::Render::ShaderData *backendShaderData1 = manager->lookupResource(id1); - Qt3DRender::Render::ShaderData *backendShaderData2 = manager->lookupResource(id2); - Qt3DRender::Render::ShaderData *backendShaderData3 = manager->lookupResource(id3); - QVERIFY(backendArrayShaderData != nullptr); - QVERIFY(backendShaderData1 != nullptr); - QVERIFY(backendShaderData2 != nullptr); - QVERIFY(backendShaderData3 != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::ShaderUniform()); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendArrayShaderData, QStringLiteral("MyBlock")); - - // THEN - QVERIFY(blockBuilder.uniforms.count() == 3); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); - - // WHEN - auto it = blockBuilder.uniforms.cbegin(); - const auto end = blockBuilder.uniforms.cend(); - - while (it != end) { - // THEN - const int nameId = Qt3DRender::Render::StringToInt::lookupId(it.key()); - QVERIFY(blockBuilder.activeUniformNamesToValue.contains(nameId)); - QCOMPARE(blockBuilder.activeUniformNamesToValue[nameId], scalarValues.value(it.key())); - ++it; - } -} - -void tst_RenderViewUtils::topLevelStructValue_data() -{ - QTest::addColumn("shaderData"); - QTest::addColumn("blockName"); - - QVariantList arrayValues2 = QVariantList() << 180 << 220 << 250 << 270 << 300 << 350 << 550; - QVariantList arrayValues = QVariantList() << 454 << 350 << 383 << 427 << 552; - - MultiLevelStructShaderData *twoLevelsNestedShaderData = new MultiLevelStructShaderData(); - MultiLevelStructShaderData *singleLevelShaderData = new MultiLevelStructShaderData(); - StructShaderData *shaderData = new StructShaderData(); - - // Don't forget to set the parent so that initBackendShaderData - // properly initializes nested members - shaderData->setParent(singleLevelShaderData); - shaderData->setArray(arrayValues); - shaderData->setScalar(1584.0f); - - singleLevelShaderData->setParent(twoLevelsNestedShaderData); - singleLevelShaderData->setInner(shaderData); - singleLevelShaderData->setScalar(1200.0f); - singleLevelShaderData->setArray(arrayValues2); - - twoLevelsNestedShaderData->setInner(singleLevelShaderData); - twoLevelsNestedShaderData->setArray(arrayValues + arrayValues2); - twoLevelsNestedShaderData->setScalar(1340.0f); - - QTest::newRow("simple struct") << shaderData << QStringLiteral("Block"); - QTest::newRow("single level inner struct") << (StructShaderData *)singleLevelShaderData << QStringLiteral("Block"); - QTest::newRow("tow level inner struct") << (StructShaderData *)twoLevelsNestedShaderData << QStringLiteral("Block"); -} - -void tst_RenderViewUtils::topLevelStructValue() -{ - // GIVEN - TestRenderer renderer; - QFETCH(StructShaderData *, shaderData); - QFETCH(QString, blockName); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - initBackendShaderData(&renderer, shaderData, manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms = shaderData->buildUniformMap(blockName); - const QHash expectedValues = shaderData->buildUniformMapValues(blockName); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, blockName); - - // THEN - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), blockBuilder.uniforms.count()); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); - - while (it != end) { - // THEN - QVERIFY(blockBuilder.uniforms.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - QVERIFY(expectedValues.contains(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - QCOMPARE(it.value(), expectedValues.value(Qt3DRender::Render::StringToInt::lookupString(it.key()))); - ++it; - } -} - -void tst_RenderViewUtils::topLevelDynamicProperties() -{ - // GIVEN - TestRenderer renderer; - QScopedPointer shaderData(new Qt3DRender::QShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - QScopedPointer texture(new Qt3DRender::QTexture2D); - QScopedPointer textureManager(new Qt3DRender::Render::TextureManager()); - - // WHEN - initBackendTexture(texture.data(), textureManager.data()); - shaderData->setProperty("scalar", 883.0f); - shaderData->setProperty("array", QVariantList() << 454 << 350 << 383 << 427 << 552); - shaderData->setProperty("texture", QVariant::fromValue(texture.data())); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - - // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; - blockBuilder.shaderDataManager = manager.data(); - blockBuilder.textureManager = textureManager.data(); - blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::ShaderUniform()); - // build name-value map - blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); - - // THEN - QVERIFY(blockBuilder.uniforms.count() == 3); - QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 3); - - QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.scalar")), - shaderData->property("scalar")); - QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.array[0]")), - shaderData->property("array")); - QCOMPARE(blockBuilder.activeUniformNamesToValue.value(Qt3DRender::Render::StringToInt::lookupId("MyBlock.texture")), - QVariant::fromValue(texture->id())); -} - -void tst_RenderViewUtils::transformedProperties() -{ - // GIVEN - QScopedPointer shaderData(new Qt3DRender::QShaderData()); - QScopedPointer manager(new Qt3DRender::Render::ShaderDataManager()); - TestRenderer renderer; - - // WHEN - const Vector3D position = Vector3D(15.0f, -5.0f, 10.0f); - const QVector3D positionQt = convertToQVector3D(position); - Matrix4x4 worldMatrix; - { - QMatrix4x4 m; - m.translate(-3.0f, 2.0f, 7.5f); - worldMatrix = Matrix4x4(m); - } - Matrix4x4 viewMatrix; - { - QMatrix4x4 m; - m.translate(9.0f, 6.0f, 12.0f); - viewMatrix = Matrix4x4(m); - } - - shaderData->setProperty("position0", positionQt); - shaderData->setProperty("position1", positionQt); - shaderData->setProperty("position2", positionQt); - shaderData->setProperty("position3", positionQt); - shaderData->setProperty("position1Transformed", Qt3DRender::Render::ShaderData::ModelToEye); - shaderData->setProperty("position2Transformed", Qt3DRender::Render::ShaderData::ModelToWorld); - shaderData->setProperty("position3Transformed", Qt3DRender::Render::ShaderData::ModelToWorldDirection); - initBackendShaderData(&renderer, shaderData.data(), manager.data()); - - // THEN - Qt3DRender::Render::ShaderData *backendShaderData = manager->lookupResource(shaderData->id()); - QVERIFY(backendShaderData != nullptr); - QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position0")), Qt3DRender::Render::ShaderData::NoTransform); - QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position1")), Qt3DRender::Render::ShaderData::ModelToEye); - QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position2")), Qt3DRender::Render::ShaderData::ModelToWorld); - QCOMPARE(backendShaderData->propertyTransformType(QStringLiteral("position3")), Qt3DRender::Render::ShaderData::ModelToWorldDirection); - - // WHEN - backendShaderData->updateWorldTransform(worldMatrix); - const Vector3D position1Value = backendShaderData->getTransformedProperty(QStringLiteral("position1"), viewMatrix).value(); - const Vector3D position2Value = backendShaderData->getTransformedProperty(QStringLiteral("position2"), viewMatrix).value(); - const Vector3D position3Value = backendShaderData->getTransformedProperty(QStringLiteral("position3"), viewMatrix).value(); - const QVariant position0Value = backendShaderData->getTransformedProperty(QStringLiteral("position0"), viewMatrix); - - // THEN - QCOMPARE(position0Value, positionQt); - QCOMPARE(position1Value, viewMatrix * worldMatrix * position); - QCOMPARE(position2Value, worldMatrix * position); - QCOMPARE(position3Value, Vector3D((worldMatrix * Vector4D(position, 0.0f)))); -} - -void tst_RenderViewUtils::shouldNotifyDynamicPropertyChanges() -{ - // GIVEN - TestArbiter arbiter; - QScopedPointer shaderData(new Qt3DRender::QShaderData()); - arbiter.setArbiterOnNode(shaderData.data()); - - // WHEN - shaderData->setProperty("scalar", 883.0f); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(arbiter.dirtyNodes.size(), 1); - QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data()); - - arbiter.dirtyNodes.clear(); - - // WHEN - QScopedPointer texture(new Qt3DRender::QTexture2D); - shaderData->setProperty("texture", QVariant::fromValue(texture.data())); - - // THEN - QCOMPARE(arbiter.events.size(), 0); - QCOMPARE(arbiter.dirtyNodes.size(), 1); - QCOMPARE(arbiter.dirtyNodes.front(), shaderData.data()); -} - -QTEST_MAIN(tst_RenderViewUtils) - -#include "tst_renderviewutils.moc" diff --git a/tests/auto/render/technique/tst_technique.cpp b/tests/auto/render/technique/tst_technique.cpp index 5b6fdb4a4..b36d00fee 100644 --- a/tests/auto/render/technique/tst_technique.cpp +++ b/tests/auto/render/technique/tst_technique.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/auto/render/textures/textures.pro b/tests/auto/render/textures/textures.pro deleted file mode 100644 index 8a7553a54..000000000 --- a/tests/auto/render/textures/textures.pro +++ /dev/null @@ -1,12 +0,0 @@ -TEMPLATE = app - -TARGET = tst_textures - -QT += core-private 3dcore 3dcore-private 3drender 3drender-private testlib - -CONFIG += testcase - -SOURCES += tst_textures.cpp - -include(../../core/common/common.pri) -include(../commons/commons.pri) diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp deleted file mode 100644 index 12d538772..000000000 --- a/tests/auto/render/textures/tst_textures.cpp +++ /dev/null @@ -1,821 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $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$ -** -****************************************************************************/ - -// TODO Remove in Qt6 -#include -QT_WARNING_DISABLE_DEPRECATED - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/** - * @brief Dummy QTextureImageDataGenerator - */ -class TestImageDataGenerator : public Qt3DRender::QTextureImageDataGenerator -{ - int m_id; -public: - TestImageDataGenerator(int id) : m_id(id) {} - - Qt3DRender::QTextureImageDataPtr operator ()() override { - return Qt3DRender::QTextureImageDataPtr::create(); - } - - bool operator ==(const Qt3DRender::QTextureImageDataGenerator &other) const override { - const TestImageDataGenerator *otherFunctor = Qt3DRender::functor_cast(&other); - return (otherFunctor != nullptr && otherFunctor->m_id == m_id); - } - - QT3D_FUNCTOR(TestImageDataGenerator) -}; - -/** - * @brief Dummy QTextureGenerator - */ -class TestTextureGenerator : public Qt3DRender::QTextureGenerator -{ - int m_id; -public: - TestTextureGenerator(int id) : m_id(id) {} - - Qt3DRender::QTextureDataPtr operator ()() override { - return Qt3DRender::QTextureDataPtr::create(); - } - - bool operator ==(const Qt3DRender::QTextureGenerator &other) const override { - const TestTextureGenerator *otherFunctor = Qt3DRender::functor_cast(&other); - return (otherFunctor != nullptr && otherFunctor->m_id == m_id); - } - - QT3D_FUNCTOR(TestTextureGenerator) -}; - -typedef QSharedPointer TestTextureGeneratorPtr; - -class TestTexturePrivate : public Qt3DRender::QAbstractTexturePrivate -{ -public: - int genId; -}; - -/** - * @brief Test QTexture. Assign texture data functor if genId > 0. - */ -class TestTexture : public Qt3DRender::QAbstractTexture -{ -public: - TestTexture(int genId, Qt3DCore::QNode *p = nullptr) - : QAbstractTexture(*new TestTexturePrivate(), p) - { - d_func()->genId = genId; - if (genId > 0) - d_func()->setDataFunctor(TestTextureGeneratorPtr::create(genId)); - } -private: - Q_DECLARE_PRIVATE(TestTexture) -}; - -class TestSharedGLTexturePrivate : public Qt3DRender::QAbstractTexturePrivate -{ -}; - -class TestSharedGLTexture : public Qt3DRender::QAbstractTexture -{ -public: - TestSharedGLTexture(int textureId, Qt3DCore::QNode *p = nullptr) - : QAbstractTexture(*new TestSharedGLTexturePrivate(), p) - { - d_func()->m_sharedTextureId = textureId; - } - -private: - Q_DECLARE_PRIVATE(TestSharedGLTexture) -}; - - -/** - * @brief Test QTextureImage - */ -class TestTextureImage : public Qt3DRender::QAbstractTextureImage -{ -public: - TestTextureImage(int genId, Qt3DCore::QNode *p = nullptr) - : QAbstractTextureImage(p) - , m_genId(genId) - { - } - - void updateGenerator() - { - Qt3DRender::QAbstractTextureImage::notifyDataGeneratorChanged(); - } - - Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const - { - return Qt3DRender::QTextureImageDataGeneratorPtr(new TestImageDataGenerator(m_genId)); - } -protected: - int m_genId; -}; - -class EmptyTextureImage : public Qt3DRender::QAbstractTextureImage -{ -public: - EmptyTextureImage(Qt3DCore::QNode *p = nullptr) - : QAbstractTextureImage(p) - { - } - - Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const - { - return {}; - } -}; - -class tst_RenderTextures : public Qt3DCore::QBackendNodeTester -{ - Q_OBJECT - - Qt3DRender::QAbstractTexture *createQTexture(int genId, - const QVector &imgGenIds, - bool genMipMaps) - { - TestTexture *tex = new TestTexture(genId); - - for (int imgGen : imgGenIds) - tex->addTextureImage(new TestTextureImage(imgGen)); - tex->setGenerateMipMaps(genMipMaps); - - return tex; - } - - Qt3DRender::QAbstractTexture *createQTextureWithTextureId(int textureId) - { - return new TestSharedGLTexture(textureId); - } - - Qt3DRender::Render::Texture *createBackendTexture(Qt3DRender::QAbstractTexture *frontend, - Qt3DRender::Render::TextureManager *texMgr, - Qt3DRender::Render::TextureImageManager *texImgMgr, - Qt3DRender::Render::AbstractRenderer *renderer) - { - Qt3DRender::Render::Texture *backend = texMgr->getOrCreateResource(frontend->id()); - backend->setRenderer(renderer); - simulateInitializationSync(frontend, backend); - - // create texture images - for (const auto texImgFrontend : frontend->textureImages()) { - // make sure TextureImageManager has backend node for this QTextureImage - if (!texImgMgr->contains(texImgFrontend->id())) { - Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id()); - texImgBackend->setRenderer(renderer); - simulateInitializationSync(texImgFrontend, texImgBackend); - } - } - - return backend; - } - -private Q_SLOTS: - - void shouldCreateSameGLTextures() - { - QSKIP("Texture Sharing is now disabled"); - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - renderer.setNodeManagers(mgrs.data()); - - // GIVEN - Qt3DRender::QAbstractTexture *tex1a = createQTexture(-1, {1,2}, true); - Qt3DRender::QAbstractTexture *tex1b = createQTexture(-1, {1,2}, true); - - // WHEN - Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - renderer.updateTexture(bt1a); - renderer.updateTexture(bt1b); - - // THEN - QCOMPARE(renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1a->peerId()), - renderer.glResourceManagers()->glTextureManager()->lookupResource(bt1b->peerId())); - renderer.shutdown(); - } - - void shouldCreateDifferentGLTexturess() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - renderer.setNodeManagers(mgrs.data()); - - // GIVEN - QVector textures; - textures << createQTexture(-1, {1,2}, true); - textures << createQTexture(-1, {1,2}, false); - textures << createQTexture(1, {1,2}, true); - textures << createQTexture(1, {1,2}, false); - textures << createQTexture(1, {1,2,3}, true); - textures << createQTexture(1, {1,2,3}, false); - - // WHEN - QVector backend; - for (auto *t : textures) { - Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - backend.push_back(backendTexture); - renderer.updateTexture(backendTexture); - } - - // THEN - - // no 2 textures must be the same - for (int i = 0; i < backend.size(); i++) - for (int k = i+1; k < backend.size(); k++) - QVERIFY(renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[i]->peerId()) != - renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[k]->peerId())); - - QVector glTextures; - for (Qt3DRender::Render::Texture *t : backend) - glTextures.push_back(renderer.glResourceManagers()->glTextureManager()->lookupResource(t->peerId())); - - // some texture generators must be the same - QVERIFY(glTextures[0]->textureGenerator().data() == nullptr); - QVERIFY(glTextures[1]->textureGenerator().data() == nullptr); - QCOMPARE(*(glTextures[2]->textureGenerator()), *(glTextures[3]->textureGenerator())); - - // some images must be the same - QCOMPARE(glTextures[0]->images(), glTextures[1]->images()); - QCOMPARE(glTextures[0]->images(), glTextures[2]->images()); - QCOMPARE(glTextures[0]->images(), glTextures[3]->images()); - QCOMPARE(glTextures[4]->images(), glTextures[5]->images()); - - QCOMPARE(glTextures[0]->properties(), glTextures[2]->properties()); - QCOMPARE(glTextures[1]->properties(), glTextures[3]->properties()); - QVERIFY(glTextures[0]->properties() != glTextures[1]->properties()); - - renderer.shutdown(); - } - - void shouldCreateDifferentGLTexturesWhenUsingSharedTextureIds() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - renderer.setNodeManagers(mgrs.data()); - - Qt3DRender::Render::GLResourceManagers *glMgrs = renderer.glResourceManagers(); - - // both texture having the same sharedTextureId - { - // GIVEN - Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1); - Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(1); - - // WHEN - Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - // THEN - QCOMPARE(bt1->sharedTextureId(), 1); - QCOMPARE(bt2->sharedTextureId(), 1); - - // WHEN - renderer.updateTexture(bt1); - renderer.updateTexture(bt2); - - // THEN - Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); - QVERIFY(glt1 != glt2); - QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); - QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); - } - - // textures having a different sharedTextureId - { - // GIVEN - Qt3DRender::QAbstractTexture *tex1a = createQTextureWithTextureId(1); - Qt3DRender::QAbstractTexture *tex1b = createQTextureWithTextureId(2); - - // WHEN - Qt3DRender::Render::Texture *bt1 = createBackendTexture(tex1a, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - Qt3DRender::Render::Texture *bt2 = createBackendTexture(tex1b, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - // THEN - QCOMPARE(bt1->sharedTextureId(), 1); - QCOMPARE(bt2->sharedTextureId(), 2); - - // WHEN - renderer.updateTexture(bt1); - renderer.updateTexture(bt2); - - // THEN - Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); - QVERIFY(glt1 != glt2); - QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); - QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); - } - - renderer.shutdown(); - } - - void generatorsShouldCreateSameData() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - renderer.setNodeManagers(mgrs.data()); - - // GIVEN - QVector textures; - textures << createQTexture(1, {1}, true); - textures << createQTexture(2, {1,2}, true); - textures << createQTexture(1, {1,2}, true); - - // WHEN - QVector backend; - for (auto *t : textures) { - Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, - mgrs->textureManager(), - mgrs->textureImageManager(), - &renderer); - backend.push_back(backendTexture); - renderer.updateTexture(backendTexture); - } - - Qt3DRender::QTextureImageDataGeneratorPtr idg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->images()[0].generator; - Qt3DRender::QTextureImageDataGeneratorPtr idg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[0].generator; - Qt3DRender::QTextureImageDataGeneratorPtr idg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->images()[1].generator; - Qt3DRender::QTextureGeneratorPtr tg1a = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[0]->peerId())->textureGenerator(); - Qt3DRender::QTextureGeneratorPtr tg1b = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[2]->peerId())->textureGenerator(); - Qt3DRender::QTextureGeneratorPtr tg2 = renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[1]->peerId())->textureGenerator(); - - // THEN - QVERIFY(idg1a); - QVERIFY(idg1b); - QVERIFY(idg2); - QVERIFY(tg1a); - QVERIFY(tg1b); - QVERIFY(tg2); - - QCOMPARE(*idg1a, *idg1b); - QVERIFY(!(*idg1a == *idg2)); - QCOMPARE(*tg1a, *tg1b); - QVERIFY(!(*tg1a == *tg2)); - - renderer.shutdown(); - } - - void checkTextureImageInitialState() - { - // GIVEN - Qt3DRender::Render::TextureImage img; - - // THEN - QCOMPARE(img.layer(), 0); - QCOMPARE(img.mipLevel(), 0); - QCOMPARE(img.isDirty(), false); - QCOMPARE(img.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); - QVERIFY(img.dataGenerator().isNull()); - } - - void checkTextureImageCleanupState() - { - // GIVEN - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - TestTextureImage img(1); - img.setLayer(2); - img.setMipLevel(3); - - // WHEN - Qt3DRender::Render::TextureImage texImgBackend; - texImgBackend.setRenderer(&renderer); - simulateInitializationSync(&img, &texImgBackend); - texImgBackend.cleanup(); - - // THEN - QCOMPARE(texImgBackend.isDirty(), false); - QCOMPARE(texImgBackend.layer(), 0); - QCOMPARE(texImgBackend.mipLevel(), 0); - QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); - QVERIFY(texImgBackend.dataGenerator().isNull()); - - renderer.shutdown(); - } - - void checkTextureImageInitializeFromPeer() - { - // GIVEN - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - TestTextureImage img(1); - - { - // WHEN - img.setLayer(2); - img.setMipLevel(3); - - Qt3DRender::Render::TextureImage texImgBackend; - texImgBackend.setRenderer(&renderer); - simulateInitializationSync(&img, &texImgBackend); - - // THEN - QCOMPARE(texImgBackend.isEnabled(), true); - QCOMPARE(texImgBackend.isDirty(), true); - QCOMPARE(texImgBackend.peerId(), img.id()); - QCOMPARE(texImgBackend.layer(), 2); - QCOMPARE(texImgBackend.mipLevel(), 3); - QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX); - QVERIFY(!texImgBackend.dataGenerator().isNull()); - } - - { - // WHEN - img.setEnabled(false); - - Qt3DRender::Render::TextureImage texImgBackend; - texImgBackend.setRenderer(&renderer); - simulateInitializationSync(&img, &texImgBackend); - - // THEN - QCOMPARE(texImgBackend.isEnabled(), false); - QCOMPARE(texImgBackend.peerId(), img.id()); - } - - renderer.shutdown(); - } - - void checkTextureImageSceneChangeEvents() - { - // GIVEN - Qt3DRender::Render::TextureImage backendImage; - TestTextureImage textureImage(1); - TestRenderer renderer; - backendImage.setRenderer(&renderer); - simulateInitializationSync(&textureImage, &backendImage); - - { - // WHEN - const bool newValue = false; - textureImage.setEnabled(newValue); - backendImage.syncFromFrontEnd(&textureImage, false); - - // THEN - QCOMPARE(backendImage.isEnabled(), newValue); - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - } - - { - // WHEN - const int newValue = 7; - textureImage.setLayer(newValue); - backendImage.syncFromFrontEnd(&textureImage, false); - - // THEN - QCOMPARE(backendImage.layer(), newValue); - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - } - - { - // WHEN - const int newValue = 3; - textureImage.setMipLevel(newValue); - backendImage.syncFromFrontEnd(&textureImage, false); - - - // THEN - QCOMPARE(backendImage.mipLevel(), newValue); - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - } - - { - // WHEN - const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeX; - textureImage.setFace(newValue); - backendImage.syncFromFrontEnd(&textureImage, false); - - // THEN - QCOMPARE(backendImage.face(), newValue); - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - } - - { - // WHEN - textureImage.updateGenerator(); - backendImage.syncFromFrontEnd(&textureImage, false); - - // THEN - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - - // WHEN - textureImage.updateGenerator(); - backendImage.syncFromFrontEnd(&textureImage, false); - - // THEN - QVERIFY(backendImage.isDirty()); - QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty); - renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty); - backendImage.unsetDirty(); - } - - renderer.shutdown(); - } - - void checkTextureImageProperlyReleaseGenerator() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); - Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); - renderer.setNodeManagers(mgrs.data()); - - // GIVEN - Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); - - Qt3DRender::Render::Texture *backendTexture = texMgr->getOrCreateResource(frontendTexture->id()); - backendTexture->setRenderer(&renderer); - simulateInitializationSync(frontendTexture, backendTexture); - - // THEN - QCOMPARE(backendTexture->textureImageIds().size(), 1); - QCOMPARE(frontendTexture->textureImages().size(), 1); - - // WHEN - TestTextureImage *texImgFrontend = static_cast(frontendTexture->textureImages().first()); - const Qt3DRender::QTextureImageDataGeneratorPtr frontendGenerator = texImgFrontend->dataGenerator(); - - // THEN - QVERIFY(!frontendGenerator.isNull()); - - // WHEN - Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id()); - texImgBackend->setRenderer(&renderer); - simulateInitializationSync(texImgFrontend, texImgBackend); - - // THEN - qDebug() << frontendGenerator << texImgBackend->dataGenerator(); - const Qt3DRender::QTextureImageDataGeneratorPtr backendGenerator = texImgFrontend->dataGenerator(); - QVERIFY(frontendGenerator != backendGenerator); - QVERIFY(*frontendGenerator == *backendGenerator); - - renderer.shutdown(); - } - - void checkTextureIsMarkedForDeletion() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); - renderer.setNodeManagers(mgrs.data()); - - Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer, - texMgr); - - // GIVEN - Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); - - Qt3DRender::Render::Texture *backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); - backendTexture->setRenderer(&renderer); - simulateInitializationSync(frontendTexture, backendTexture); - - // THEN - QVERIFY(backendTexture != nullptr); - QCOMPARE(texMgr->textureIdsToCleanup().size(), 0); - - QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture); - - // WHEN - textureBackendNodeMapper.destroy(frontendTexture->id()); - - // THEN - QCOMPARE(texMgr->textureIdsToCleanup().size(), 1); - QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id()); - QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr); - - renderer.shutdown(); - } - - void checkTextureDestructionReconstructionWithinSameLoop() - { - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); - renderer.setNodeManagers(mgrs.data()); - - Qt3DRender::Render::TextureFunctor textureBackendNodeMapper(&renderer, - texMgr); - - // GIVEN - Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true); - - Qt3DRender::Render::Texture *backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); - backendTexture->setRenderer(&renderer); - simulateInitializationSync(frontendTexture, backendTexture); - - // WHEN - textureBackendNodeMapper.destroy(frontendTexture->id()); - - // THEN - QCOMPARE(texMgr->textureIdsToCleanup().size(), 1); - QCOMPARE(texMgr->textureIdsToCleanup().first(), frontendTexture->id()); - QVERIFY(texMgr->lookupResource(frontendTexture->id()) == nullptr); - - // WHEN - backendTexture = static_cast(textureBackendNodeMapper.create(creationChange(frontendTexture))); - backendTexture->setRenderer(&renderer); - simulateInitializationSync(frontendTexture, backendTexture); - - // THEN - QVERIFY(backendTexture != nullptr); - QCOMPARE(texMgr->textureIdsToCleanup().size(), 0); - QCOMPARE(texMgr->lookupResource(frontendTexture->id()), backendTexture); - - renderer.shutdown(); - } - - void checkTextureImageDirtinessPropagatesToTextures() - { - // GIVEN - QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); - Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); - renderer.setNodeManagers(mgrs.data()); - - Qt3DRender::QTexture2D *texture1 = new Qt3DRender::QTexture2D(); - TestTextureImage *image1 = new TestTextureImage(1); - - Qt3DRender::QTexture2D *texture2 = new Qt3DRender::QTexture2D(); - TestTextureImage *image2 = new TestTextureImage(2); - - Qt3DRender::QTexture2D *texture3 = new Qt3DRender::QTexture2D(); - - texture1->addTextureImage(image1); - texture2->addTextureImage(image2); - texture3->addTextureImage(image1); - texture3->addTextureImage(image2); - - Qt3DRender::Render::Texture *backendTexture1 = texMgr->getOrCreateResource(texture1->id()); - Qt3DRender::Render::Texture *backendTexture2 = texMgr->getOrCreateResource(texture2->id()); - Qt3DRender::Render::Texture *backendTexture3 = texMgr->getOrCreateResource(texture3->id()); - Qt3DRender::Render::TextureImage *backendImage1 = texImgMgr->getOrCreateResource(image1->id()); - Qt3DRender::Render::TextureImage *backendImage2 = texImgMgr->getOrCreateResource(image2->id()); - - backendTexture1->setRenderer(&renderer); - backendTexture2->setRenderer(&renderer); - backendTexture3->setRenderer(&renderer); - backendImage1->setRenderer(&renderer); - backendImage2->setRenderer(&renderer); - - simulateInitializationSync(texture1, backendTexture1); - simulateInitializationSync(texture2, backendTexture2); - simulateInitializationSync(texture3, backendTexture3); - simulateInitializationSync(image1, backendImage1); - simulateInitializationSync(image2, backendImage2); - - // THEN - QCOMPARE(backendTexture1->textureImageIds().size(), 1); - QCOMPARE(backendTexture1->textureImageIds().first(), image1->id()); - QCOMPARE(backendTexture2->textureImageIds().size(), 1); - QCOMPARE(backendTexture2->textureImageIds().first(), image2->id()); - QCOMPARE(backendTexture3->textureImageIds().size(), 2); - QCOMPARE(backendTexture3->textureImageIds().first(), image1->id()); - QCOMPARE(backendTexture3->textureImageIds().last(), image2->id()); - - // WHEN - backendTexture1->unsetDirty(); - backendTexture2->unsetDirty(); - backendTexture3->unsetDirty(); - backendImage1->unsetDirty(); - backendImage2->unsetDirty(); - - // THEN - QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - - // WHEN - renderer.textureGathererJob()->run(); - - // THEN - QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - - // WHEN - // Make Image1 dirty - image1->updateGenerator(); - backendImage1->syncFromFrontEnd(image1, false); - - // THEN - QVERIFY(backendImage1->isDirty()); - QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - - // WHEN - renderer.textureGathererJob()->run(); - - // THEN - QVERIFY(backendTexture1->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); - QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); - - backendImage1->unsetDirty(); - backendTexture1->unsetDirty(); - backendTexture3->unsetDirty(); - - // WHEN - image2->updateGenerator(); - backendImage2->syncFromFrontEnd(image2, false); - - // THEN - QVERIFY(backendImage2->isDirty()); - QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture2->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture3->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - - // WHEN - renderer.textureGathererJob()->run(); - - QVERIFY(backendTexture1->dirtyFlags() == Qt3DRender::Render::Texture::NotDirty); - QVERIFY(backendTexture2->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); - QVERIFY(backendTexture3->dirtyFlags() & Qt3DRender::Render::Texture::DirtyImageGenerators); - - renderer.shutdown(); - } -}; - -QTEST_MAIN(tst_RenderTextures) - -#include "tst_textures.moc" diff --git a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp index 287a17b84..24d7ff643 100644 --- a/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp +++ b/tests/auto/render/trianglesextractor/tst_trianglesextractor.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/benchmarks/render/jobs/jobs.pro b/tests/benchmarks/render/jobs/jobs.pro index bfd0f1317..71b0ef409 100644 --- a/tests/benchmarks/render/jobs/jobs.pro +++ b/tests/benchmarks/render/jobs/jobs.pro @@ -7,3 +7,7 @@ QT += testlib core core-private 3dcore 3dcore-private 3drender 3drender-private SOURCES += tst_bench_jobs.cpp DEFINES += QT3D_RENDER_UNIT_TESTS +DEFINES += QT_BUILD_INTERNAL + +# Link Against OpenGL Renderer Plugin +include(../../../auto/render/opengl/opengl_render_plugin.pri) diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp index b611f3cdc..87689e46c 100644 --- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp +++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp @@ -41,7 +41,6 @@ #include #include #include -#include #include #include #include @@ -50,6 +49,7 @@ #include #include #include +#include #include #include diff --git a/tests/benchmarks/render/materialparametergathering/materialparametergathering.pro b/tests/benchmarks/render/materialparametergathering/materialparametergathering.pro index e227a08a0..a20372163 100644 --- a/tests/benchmarks/render/materialparametergathering/materialparametergathering.pro +++ b/tests/benchmarks/render/materialparametergathering/materialparametergathering.pro @@ -12,3 +12,6 @@ include(../../../auto/render/commons/commons.pri) # Needed to use the TestAspect DEFINES += QT_BUILD_INTERNAL + +# Link Against OpenGL Renderer Plugin +include(../../../auto/render/opengl/opengl_render_plugin.pri) diff --git a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp index 210d82dcf..644c4d74c 100644 --- a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp +++ b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 01358191691cc81acb58afba6f82e800bc1b427c Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Mon, 12 Mar 2018 15:23:34 +0100 Subject: Move classes in OpenGL renderer plugin into an OpenGL namespace Change-Id: I5314da1df7fbfd1b6db4412e7bc71231525d9de2 Reviewed-by: Mike Krus --- .../opengl/computecommand/tst_computecommand.cpp | 4 +- .../tst_filtercompatibletechniquejob.cpp | 10 +-- .../opengl/glshadermanager/tst_glshadermanager.cpp | 26 +++---- .../graphicshelpergl2/tst_graphicshelpergl2.cpp | 1 + .../tst_graphicshelpergl3_2.cpp | 1 + .../tst_graphicshelpergl3_3.cpp | 1 + .../graphicshelpergl4/tst_graphicshelpergl4.cpp | 1 + .../tst_materialparametergathererjob.cpp | 56 +++++++-------- .../opengl/qgraphicsutils/tst_qgraphicsutils.cpp | 76 ++++++++++---------- tests/auto/render/opengl/renderer/tst_renderer.cpp | 12 ++-- .../render/opengl/renderqueue/tst_renderqueue.cpp | 32 ++++----- .../renderviewbuilder/tst_renderviewbuilder.cpp | 49 ++++++------- .../render/opengl/renderviews/tst_renderviews.cpp | 20 +++--- .../opengl/renderviewutils/tst_renderviewutils.cpp | 80 +++++++++++----------- tests/auto/render/opengl/textures/tst_textures.cpp | 32 ++++----- tests/benchmarks/render/jobs/tst_bench_jobs.cpp | 22 +++--- .../tst_bench_materialparametergathering.cpp | 6 +- 17 files changed, 219 insertions(+), 210 deletions(-) (limited to 'tests') diff --git a/tests/auto/render/opengl/computecommand/tst_computecommand.cpp b/tests/auto/render/opengl/computecommand/tst_computecommand.cpp index 80cbfb090..3caf11c8f 100644 --- a/tests/auto/render/opengl/computecommand/tst_computecommand.cpp +++ b/tests/auto/render/opengl/computecommand/tst_computecommand.cpp @@ -44,11 +44,11 @@ // tst_Renderer is a friend class of Renderer -class tst_Renderer : public Qt3DRender::Render::Renderer +class tst_Renderer : public Qt3DRender::Render::OpenGL::Renderer { public: tst_Renderer() - : Qt3DRender::Render::Renderer(Qt3DRender::QRenderAspect::Synchronous) + : Qt3DRender::Render::OpenGL::Renderer(Qt3DRender::QRenderAspect::Synchronous) {} ~tst_Renderer() { diff --git a/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp b/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp index 8b9390340..e5c34f804 100644 --- a/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp +++ b/tests/auto/render/opengl/filtercompatibletechniquejob/tst_filtercompatibletechniquejob.cpp @@ -116,9 +116,9 @@ public: renderer()->submissionContext()->beginDrawing(m_window.data()); } - Render::Renderer *renderer() const + Render::OpenGL::Renderer *renderer() const { - return static_cast(d_func()->m_renderer); + return static_cast(d_func()->m_renderer); } void onRegistered() { QRenderAspect::onRegistered(); } @@ -196,7 +196,7 @@ private Q_SLOTS: void checkInitialState() { // GIVEN - Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; + Qt3DRender::Render::OpenGL::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; // THEN QVERIFY(backendFilterCompatibleTechniqueJob.manager() == nullptr); @@ -204,7 +204,7 @@ private Q_SLOTS: // WHEN Qt3DRender::Render::TechniqueManager techniqueManager; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); backendFilterCompatibleTechniqueJob.setManager(&techniqueManager); backendFilterCompatibleTechniqueJob.setRenderer(&renderer); @@ -218,7 +218,7 @@ private Q_SLOTS: void checkRunRendererRunning() { // GIVEN - Qt3DRender::Render::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; + Qt3DRender::Render::OpenGL::FilterCompatibleTechniqueJob backendFilterCompatibleTechniqueJob; Qt3DRender::TestAspect testAspect(buildTestScene()); const bool unableToCreateContext = !testAspect.contextCreationSuccessful(); diff --git a/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp b/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp index 83420af3b..6a5bc87ea 100644 --- a/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp +++ b/tests/auto/render/opengl/glshadermanager/tst_glshadermanager.cpp @@ -46,7 +46,7 @@ private Q_SLOTS: void tst_GLShaderManager::adopt() { // GIVEN - Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::Render::OpenGL::GLShaderManager cache; Qt3DRender::QShaderProgram frontendShader1; Qt3DRender::QShaderProgram frontendShader2; TestRenderer renderer; @@ -64,7 +64,7 @@ void tst_GLShaderManager::adopt() QVERIFY(backendShaderNode1.peerId() != backendShaderNode2.peerId()); // WHEN - Qt3DRender::Render::GLShader *glShader1 = cache.createOrAdoptExisting(&backendShaderNode1); + Qt3DRender::Render::OpenGL::GLShader *glShader1 = cache.createOrAdoptExisting(&backendShaderNode1); // THEN QVERIFY(glShader1 != nullptr); @@ -73,7 +73,7 @@ void tst_GLShaderManager::adopt() QCOMPARE(shaderNodeIds.first(), backendShaderNode1.peerId()); // WHEN - Qt3DRender::Render::GLShader *glShader2 = cache.createOrAdoptExisting(&backendShaderNode2); + Qt3DRender::Render::OpenGL::GLShader *glShader2 = cache.createOrAdoptExisting(&backendShaderNode2); // THEN QCOMPARE(glShader1, glShader2); @@ -87,7 +87,7 @@ void tst_GLShaderManager::adopt() void tst_GLShaderManager::lookupResource() { // GIVEN - Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::Render::OpenGL::GLShaderManager cache; Qt3DRender::QShaderProgram frontendShader1; Qt3DRender::QShaderProgram frontendShader2; TestRenderer renderer; @@ -104,8 +104,8 @@ void tst_GLShaderManager::lookupResource() cache.createOrAdoptExisting(&backendShaderNode2); // THEN - Qt3DRender::Render::GLShader *glShader1 = cache.lookupResource(backendShaderNode1.peerId()); - Qt3DRender::Render::GLShader *glShader2 = cache.lookupResource(backendShaderNode2.peerId()); + Qt3DRender::Render::OpenGL::GLShader *glShader1 = cache.lookupResource(backendShaderNode1.peerId()); + Qt3DRender::Render::OpenGL::GLShader *glShader2 = cache.lookupResource(backendShaderNode2.peerId()); QVERIFY(glShader1 != nullptr); QCOMPARE(glShader1, glShader2); const QVector shaderNodeIds = cache.shaderIdsForProgram(glShader1); @@ -117,7 +117,7 @@ void tst_GLShaderManager::lookupResource() void tst_GLShaderManager::abandon() { // GIVEN - Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::Render::OpenGL::GLShaderManager cache; Qt3DRender::QShaderProgram frontendShader1; Qt3DRender::QShaderProgram frontendShader2; TestRenderer renderer; @@ -132,7 +132,7 @@ void tst_GLShaderManager::abandon() cache.createOrAdoptExisting(&backendShaderNode2); // WHEN - Qt3DRender::Render::GLShader *glShader = cache.lookupResource(backendShaderNode1.peerId()); + Qt3DRender::Render::OpenGL::GLShader *glShader = cache.lookupResource(backendShaderNode1.peerId()); cache.abandon(glShader, &backendShaderNode1); // THEN @@ -147,7 +147,7 @@ void tst_GLShaderManager::abandon() // THEN shaderNodeIds = cache.shaderIdsForProgram(glShader); QCOMPARE(shaderNodeIds.size(), 0); - const QVector releasedShaders = cache.takeAbandonned(); + const QVector releasedShaders = cache.takeAbandonned(); QCOMPARE(releasedShaders.size(), 1); QCOMPARE(releasedShaders.first(), glShader); } @@ -155,7 +155,7 @@ void tst_GLShaderManager::abandon() void tst_GLShaderManager::insertAfterRemoval() { // GIVEN - Qt3DRender::Render::GLShaderManager cache; + Qt3DRender::Render::OpenGL::GLShaderManager cache; Qt3DRender::QShaderProgram frontendShader; TestRenderer renderer; Qt3DRender::Render::Shader backendShaderNode; @@ -165,8 +165,8 @@ void tst_GLShaderManager::insertAfterRemoval() simulateInitialization(&frontendShader, &backendShaderNode); // WHEN - Qt3DRender::Render::GLShader *apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); - const Qt3DRender::Render::GLShader *originalApiShader = apiShader1; + Qt3DRender::Render::OpenGL::GLShader *apiShader1 = cache.createOrAdoptExisting(&backendShaderNode); + const Qt3DRender::Render::OpenGL::GLShader *originalApiShader = apiShader1; // THEN auto apiShader2 = cache.lookupResource(frontendShader.id()); @@ -179,7 +179,7 @@ void tst_GLShaderManager::insertAfterRemoval() cache.abandon(apiShader1, &backendShaderNode); // THEN - Qt3DRender::Render::GLShader *apiShaderEmpty = cache.lookupResource(frontendShader.id()); + Qt3DRender::Render::OpenGL::GLShader *apiShaderEmpty = cache.lookupResource(frontendShader.id()); QVERIFY(apiShaderEmpty == nullptr); // WHEN diff --git a/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp b/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp index 0a43a3040..5a1d22283 100644 --- a/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp +++ b/tests/auto/render/opengl/graphicshelpergl2/tst_graphicshelpergl2.cpp @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE using namespace Qt3DRender; using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::OpenGL; namespace { diff --git a/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp b/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp index a4a59d7c4..08c30dc15 100644 --- a/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp +++ b/tests/auto/render/opengl/graphicshelpergl3_2/tst_graphicshelpergl3_2.cpp @@ -43,6 +43,7 @@ using namespace Qt3DRender; using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::OpenGL; namespace { diff --git a/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp index 3e4a052ba..b463e6236 100644 --- a/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp +++ b/tests/auto/render/opengl/graphicshelpergl3_3/tst_graphicshelpergl3_3.cpp @@ -42,6 +42,7 @@ using namespace Qt3DRender; using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::OpenGL; namespace { diff --git a/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp index 31024e1db..8f86f38ce 100644 --- a/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -43,6 +43,7 @@ using namespace Qt3DRender; using namespace Qt3DRender::Render; +using namespace Qt3DRender::Render::OpenGL; namespace { diff --git a/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp b/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp index e6b78c47b..efd2c6603 100644 --- a/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp +++ b/tests/auto/render/opengl/materialparametergathererjob/tst_materialparametergathererjob.cpp @@ -107,9 +107,9 @@ public: d_func()->m_renderer->initialize(); } - Render::MaterialParameterGathererJobPtr materialGathererJob() const + Render::OpenGL::MaterialParameterGathererJobPtr materialGathererJob() const { - Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); + Render::OpenGL::MaterialParameterGathererJobPtr job = Render::OpenGL::MaterialParameterGathererJobPtr::create(); job->setNodeManagers(nodeManagers()); return job; } @@ -232,7 +232,7 @@ private Q_SLOTS: // GIVEN Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph()); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -252,7 +252,7 @@ private Q_SLOTS: TestMaterial material; Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -274,7 +274,7 @@ private Q_SLOTS: material.setEnabled(false); Qt3DCore::QEntity *sceneRoot = buildScene(viewportFrameGraph(), &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -306,7 +306,7 @@ private Q_SLOTS: Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -346,7 +346,7 @@ private Q_SLOTS: Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -382,7 +382,7 @@ private Q_SLOTS: Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -416,7 +416,7 @@ private Q_SLOTS: Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -456,7 +456,7 @@ private Q_SLOTS: Qt3DCore::QEntity *sceneRoot = buildScene(frameGraphFilter, &material); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); @@ -509,7 +509,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -526,10 +526,10 @@ private Q_SLOTS: // THEN -> RenderPassFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(renderPassParameter->id())); @@ -565,7 +565,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -582,10 +582,10 @@ private Q_SLOTS: // THEN -> TechniqueFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueFilterParameter->id())); @@ -620,7 +620,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -637,10 +637,10 @@ private Q_SLOTS: // THEN -> TechniqueFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(materialParameter->id())); @@ -674,7 +674,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -691,10 +691,10 @@ private Q_SLOTS: // THEN -> TechniqueFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(effectParameter->id())); @@ -724,7 +724,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -741,10 +741,10 @@ private Q_SLOTS: // THEN -> TechniqueFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(techniqueParam->id())); @@ -768,7 +768,7 @@ private Q_SLOTS: material.es2Pass()->addParameter(passParam); Qt3DRender::TestAspect testAspect(sceneRoot); - Qt3DRender::Render::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatherer = testAspect.materialGathererJob(); testAspect.initializeRenderer(); QCOMPARE(testAspect.nodeManagers()->materialManager()->activeHandles().size(), 1); @@ -785,10 +785,10 @@ private Q_SLOTS: // THEN -> TechniqueFilter wins QCOMPARE(gatherer->materialToPassAndParameter().size(), 1); - const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); + const QVector passParameterData = gatherer->materialToPassAndParameter().begin().value(); QCOMPARE(passParameterData.size(), 1); - const Qt3DRender::Render::RenderPassParameterData data = passParameterData.first(); + const Qt3DRender::Render::OpenGL::RenderPassParameterData data = passParameterData.first(); QCOMPARE(data.parameterInfo.size(), 1); QCOMPARE(data.parameterInfo.first().handle, testAspect.nodeManagers()->parameterManager()->lookupHandle(passParam->id())); diff --git a/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp b/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp index 2e0dd0f96..bd4772045 100644 --- a/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp +++ b/tests/auto/render/opengl/qgraphicsutils/tst_qgraphicsutils.cpp @@ -44,14 +44,14 @@ private slots: void tst_QGraphicsUtils::fillScalarInDataArray() { - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 1; description.m_offset = 0; description.m_arrayStride = 10; QVector4D testVector(8.0f, 8.0f, 3.0f, 1.0f); - const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(testVector, 1, 4); + const GLfloat *vectorData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(testVector, 1, 4); for (int i = 0; i < 4; i++) { if (i == 0) @@ -68,7 +68,7 @@ void tst_QGraphicsUtils::fillScalarInDataArray() char *innerData = data.data(); // Checked that we are not overflowing - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 2); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 2); for (int i = 0; i < 4; ++i) { if (i < 2) QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); @@ -77,7 +77,7 @@ void tst_QGraphicsUtils::fillScalarInDataArray() } // Check that all values are copied - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); for (int i = 0; i < 4; ++i) QVERIFY(vectorData[i] == ((GLfloat*)innerData)[i]); @@ -86,7 +86,7 @@ void tst_QGraphicsUtils::fillScalarInDataArray() data = QByteArray(description.m_size * 8 * sizeof(GLfloat), 0); innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); for (int i = 0; i < 8; ++i) { if (i < 4) QVERIFY(((GLfloat*)innerData)[i] == 0.0f); @@ -102,9 +102,9 @@ void tst_QGraphicsUtils::fillArray() QVector4D testVector3(4.0f, 5.0f, 4.0f, 2.0f); QVariantList variantList = QVariantList() << testVector << testVector2 << testVector3; - const GLfloat *vectorData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant(variantList), 3, 4); + const GLfloat *vectorData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(QVariant(variantList), 3, 4); - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 3; description.m_offset = 16; @@ -112,7 +112,7 @@ void tst_QGraphicsUtils::fillArray() QByteArray data(description.m_size * (4 + description.m_arrayStride) * sizeof(GLfloat) + description.m_offset, 0); char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, vectorData, description, 4); int offset = description.m_offset / sizeof(GLfloat); int stride = description.m_arrayStride / sizeof(GLfloat); @@ -144,25 +144,25 @@ void tst_QGraphicsUtils::fillScalarWithOffsets() QVector4D color(4.0f, 5.0f, 4.0f, 1.0f); float intensity = 1.0f; - Qt3DRender::Render::ShaderUniform posUniform; + Qt3DRender::Render::OpenGL::ShaderUniform posUniform; posUniform.m_size = 1; posUniform.m_arrayStride = 0; posUniform.m_matrixStride = 0; posUniform.m_offset = 0; - Qt3DRender::Render::ShaderUniform dirUniform; + Qt3DRender::Render::OpenGL::ShaderUniform dirUniform; dirUniform.m_size = 1; dirUniform.m_arrayStride = 0; dirUniform.m_matrixStride = 0; dirUniform.m_offset = 16; - Qt3DRender::Render::ShaderUniform colUniform; + Qt3DRender::Render::OpenGL::ShaderUniform colUniform; colUniform.m_size = 1; colUniform.m_arrayStride = 0; colUniform.m_matrixStride = 0; colUniform.m_offset = 32; - Qt3DRender::Render::ShaderUniform intUniform; + Qt3DRender::Render::OpenGL::ShaderUniform intUniform; intUniform.m_size = 1; intUniform.m_arrayStride = 0; intUniform.m_matrixStride = 0; @@ -171,18 +171,18 @@ void tst_QGraphicsUtils::fillScalarWithOffsets() QVector data(16); void *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(position, 1, 3), - posUniform, 3); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(direction, 1, 3), - dirUniform, 3); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(color, 1, 4), - colUniform, 4); - Qt3DRender::Render::QGraphicsUtils::fillDataArray(innerData, - Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(intensity, 1, 1), - intUniform, 1); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(position, 1, 3), + posUniform, 3); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(direction, 1, 3), + dirUniform, 3); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(color, 1, 4), + colUniform, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataArray(innerData, + Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(intensity, 1, 1), + intUniform, 1); GLfloat *floatData = (GLfloat*)innerData; @@ -214,9 +214,9 @@ void tst_QGraphicsUtils::fillMatrix4x4() QMatrix4x4 mat(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f, 16.0f); // column major - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(mat, 1, 16); + const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(mat, 1, 16); - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 1; description.m_offset = 0; @@ -226,7 +226,7 @@ void tst_QGraphicsUtils::fillMatrix4x4() QByteArray data(description.m_size * 16 * sizeof(GLfloat), 0); char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check for no offset/no stride for (int i = 0; i < 16; ++i) QVERIFY((((GLfloat *)innerData)[i]) == matData[i]); @@ -234,7 +234,7 @@ void tst_QGraphicsUtils::fillMatrix4x4() description.m_offset = 12; data = QByteArray((description.m_size * 16 + description.m_offset) * sizeof(GLfloat), 0); innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check with 12 offset/no stride for (int i = 0; i < 16; ++i) QVERIFY((((GLfloat *)innerData)[3 + i]) == matData[i]); @@ -242,7 +242,7 @@ void tst_QGraphicsUtils::fillMatrix4x4() description.m_matrixStride = 16; data = QByteArray((description.m_size * 16 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 4); // Check with 10 offset/ 16 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); @@ -259,9 +259,9 @@ void tst_QGraphicsUtils::fillMatrix3x4() QMatrix3x4 mat; mat.fill(6.0f); - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); + const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 1; description.m_offset = 16; @@ -270,7 +270,7 @@ void tst_QGraphicsUtils::fillMatrix3x4() QByteArray data((description.m_size * 12 + 3 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 3, 4); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 3, 4); // Check with 16 offset/ 12 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); @@ -287,9 +287,9 @@ void tst_QGraphicsUtils::fillMatrix4x3() QMatrix4x3 mat; mat.fill(6.0f); - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); + const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(mat), 1, 12); - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 1; description.m_offset = 16; @@ -298,7 +298,7 @@ void tst_QGraphicsUtils::fillMatrix4x3() QByteArray data((description.m_size * 12 + 4 * description.m_matrixStride + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); // Check with 16 offset/ 16 stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); @@ -321,9 +321,9 @@ void tst_QGraphicsUtils::fillMatrixArray() QVariantList matrices = QVariantList() << QVariant::fromValue(mat1) << QVariant::fromValue(mat2) << QVariant::fromValue(mat3); - const GLfloat *matData = Qt3DRender::Render::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(matrices), 3, 12); + const GLfloat *matData = Qt3DRender::Render::OpenGL::QGraphicsUtils::valueArrayFromVariant(QVariant::fromValue(matrices), 3, 12); - Qt3DRender::Render::ShaderUniform description; + Qt3DRender::Render::OpenGL::ShaderUniform description; description.m_size = 3; description.m_offset = 12; @@ -332,7 +332,7 @@ void tst_QGraphicsUtils::fillMatrixArray() QByteArray data((description.m_size * (12 + 4 * description.m_matrixStride + description.m_arrayStride) + description.m_offset) * sizeof(GLfloat), 0); char *innerData = data.data(); - Qt3DRender::Render::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); + Qt3DRender::Render::OpenGL::QGraphicsUtils::fillDataMatrixArray(innerData, matData, description, 4, 3); // Check with 12 offset/ 4 array stride / 16 matrix stride int offset = description.m_offset / sizeof(GLfloat); int matrixStride = description.m_matrixStride / sizeof(GLfloat); diff --git a/tests/auto/render/opengl/renderer/tst_renderer.cpp b/tests/auto/render/opengl/renderer/tst_renderer.cpp index 6aed6ed5f..db7a37af1 100644 --- a/tests/auto/render/opengl/renderer/tst_renderer.cpp +++ b/tests/auto/render/opengl/renderer/tst_renderer.cpp @@ -50,7 +50,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); Qt3DRender::Render::RenderSettings settings; // owned by FG manager @@ -107,8 +107,8 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); - Qt3DRender::Render::RenderQueue *renderQueue = renderer.renderQueue(); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::RenderQueue *renderQueue = renderer.renderQueue(); Qt3DRender::Render::OffscreenSurfaceHelper offscreenHelper(&renderer); Qt3DRender::Render::RenderSettings settings; // owned by FG manager @@ -129,16 +129,16 @@ private Q_SLOTS: // NOTE: FilterCompatibleTechniqueJob and ShaderGathererJob cannot run because the context // is not initialized in this test - const int renderViewBuilderMaterialCacheJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + const int renderViewBuilderMaterialCacheJobCount = 1 + Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount(); // syncMaterialGathererJob // n * materialGathererJob const int layerCacheJobCount = 2; // filterEntityByLayerJob, // syncFilterEntityByLayerJob - const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + const int singleRenderViewCommandRebuildJobCount = 1 + Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount(); - const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount(); + const int singleRenderViewJobCount = 8 + 1 * Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount(); // RenderViewBuilder renderViewJob, // syncRenderViewInitializationJob, // syncFrustumCullingJob, diff --git a/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp b/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp index 2be089495..728648a3c 100644 --- a/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp +++ b/tests/auto/render/opengl/renderqueue/tst_renderqueue.cpp @@ -53,7 +53,7 @@ private Q_SLOTS: void tst_RenderQueue::setRenderViewCount() { // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; + Qt3DRender::Render::OpenGL::RenderQueue renderQueue; // THEN QCOMPARE(renderQueue.wasReset(), true); @@ -70,7 +70,7 @@ void tst_RenderQueue::setRenderViewCount() void tst_RenderQueue::circleQueues() { // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; + Qt3DRender::Render::OpenGL::RenderQueue renderQueue; renderQueue.setTargetRenderViewCount(7); // WHEN @@ -85,9 +85,9 @@ void tst_RenderQueue::circleQueues() QCOMPARE(renderQueue.currentRenderViewCount(), 0); // WHEN - QList renderViews; + QList renderViews; for (int i = 0; i < 7; i++) { - renderViews << new Qt3DRender::Render::RenderView(); + renderViews << new Qt3DRender::Render::OpenGL::RenderView(); renderQueue.queueRenderView(renderViews.at(i), i); } @@ -99,19 +99,19 @@ void tst_RenderQueue::circleQueues() void tst_RenderQueue::checkOrder() { // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; + Qt3DRender::Render::OpenGL::RenderQueue renderQueue; renderQueue.setTargetRenderViewCount(7); - QVector renderViews(7); + QVector renderViews(7); // WHEN for (int i = 0; i < 7; ++i) { int processingOrder = (i % 2 == 0) ? (6 - i) : i; - renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); + renderViews[processingOrder] = new Qt3DRender::Render::OpenGL::RenderView(); renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); } // THEN - QVector frame = renderQueue.nextFrameQueue(); + QVector frame = renderQueue.nextFrameQueue(); for (int i = 0; i < 7; ++i) { QVERIFY(frame[i] == renderViews[i]); } @@ -120,14 +120,14 @@ void tst_RenderQueue::checkOrder() void tst_RenderQueue::checkTimeToSubmit() { // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; + Qt3DRender::Render::OpenGL::RenderQueue renderQueue; renderQueue.setTargetRenderViewCount(7); - QVector renderViews(7); + QVector renderViews(7); // WHEN for (int i = 0; i < 7; i++) { int processingOrder = (i % 2 == 0) ? (6 - i) : i; - renderViews[processingOrder] = new Qt3DRender::Render::RenderView(); + renderViews[processingOrder] = new Qt3DRender::Render::OpenGL::RenderView(); renderQueue.queueRenderView(renderViews[processingOrder], processingOrder); // THEN @@ -144,7 +144,7 @@ class SimpleWorker : public QThread public: QSemaphore m_waitSubmit; QSemaphore m_waitQueue; - Qt3DRender::Render::RenderQueue *m_renderQueues; + Qt3DRender::Render::OpenGL::RenderQueue *m_renderQueues; public Q_SLOTS: @@ -160,7 +160,7 @@ public Q_SLOTS: // THEN QCOMPARE(m_renderQueues->currentRenderViewCount(), j); // WHEN - m_renderQueues->queueRenderView(new Qt3DRender::Render::RenderView(), j); + m_renderQueues->queueRenderView(new Qt3DRender::Render::OpenGL::RenderView(), j); // THEN QVERIFY(m_renderQueues->targetRenderViewCount() == 7); QCOMPARE(m_renderQueues->currentRenderViewCount(), j + 1); @@ -178,7 +178,7 @@ public Q_SLOTS: void tst_RenderQueue::concurrentQueueAccess() { // GIVEN - Qt3DRender::Render::RenderQueue *renderQueue = new Qt3DRender::Render::RenderQueue; + Qt3DRender::Render::OpenGL::RenderQueue *renderQueue = new Qt3DRender::Render::OpenGL::RenderQueue; SimpleWorker *jobsThread = new SimpleWorker(); renderQueue->setTargetRenderViewCount(7); @@ -212,7 +212,7 @@ void tst_RenderQueue::concurrentQueueAccess() void tst_RenderQueue::resetQueue() { // GIVEN - Qt3DRender::Render::RenderQueue renderQueue; + Qt3DRender::Render::OpenGL::RenderQueue renderQueue; for (int j = 0; j < 5; j++) { // WHEN @@ -222,7 +222,7 @@ void tst_RenderQueue::resetQueue() QVERIFY(renderQueue.currentRenderViewCount() == 0); // WHEN - QVector renderViews(5); + QVector renderViews(5); for (int i = 0; i < 5; ++i) { renderQueue.queueRenderView(renderViews.at(i), i); } diff --git a/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp index 6dc463589..fe534e243 100644 --- a/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp +++ b/tests/auto/render/opengl/renderviewbuilder/tst_renderviewbuilder.cpp @@ -96,14 +96,14 @@ public: return d_func()->m_renderer->nodeManagers(); } - Render::Renderer *renderer() const + Render::OpenGL::Renderer *renderer() const { - return static_cast(d_func()->m_renderer); + return static_cast(d_func()->m_renderer); } - Render::MaterialParameterGathererJobPtr materialGathererJob() const + Render::OpenGL::MaterialParameterGathererJobPtr materialGathererJob() const { - Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); + Render::OpenGL::MaterialParameterGathererJobPtr job = Render::OpenGL::MaterialParameterGathererJobPtr::create(); job->setNodeManagers(nodeManagers()); return job; } @@ -216,7 +216,7 @@ private Q_SLOTS: { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); // THEN QCOMPARE(renderViewBuilder.renderViewIndex(), 0); @@ -247,14 +247,14 @@ private Q_SLOTS: QVERIFY(renderViewBuilder.filterEntityByLayerJob().isNull()); QVERIFY(renderViewBuilder.syncFilterEntityByLayerJob().isNull()); - QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.renderViewCommandUpdaterJobs().size(), Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount()); QCOMPARE(renderViewBuilder.materialGathererJobs().size(), 0); - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 8 + 1 * Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount()); } { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); @@ -264,22 +264,22 @@ private Q_SLOTS: QVERIFY(!renderViewBuilder.syncFilterEntityByLayerJob().isNull()); // mark jobs dirty and recheck - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 10 + 1 * Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount()); } { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); // THEN QCOMPARE(renderViewBuilder.materialGathererCacheNeedsToBeRebuilt(), true); - QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.materialGathererJobs().size(), Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount()); QVERIFY(!renderViewBuilder.syncMaterialGathererJob().isNull()); // mark jobs dirty and recheck - QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::RenderViewBuilder::optimalJobCount()); + QCOMPARE(renderViewBuilder.buildJobHierachy().size(), 9 + 2 * Qt3DRender::Render::OpenGL::RenderViewBuilder::optimalJobCount()); } } @@ -296,7 +296,7 @@ private Q_SLOTS: { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); @@ -357,7 +357,7 @@ private Q_SLOTS: } { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); renderViewBuilder.setMaterialGathererCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); @@ -441,7 +441,7 @@ private Q_SLOTS: QVERIFY(leafNode != nullptr); // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); renderViewBuilder.renderViewJob()->run(); @@ -456,7 +456,7 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + Qt3DRender::Render::OpenGL::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); @@ -476,7 +476,7 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + Qt3DRender::Render::OpenGL::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); @@ -495,7 +495,7 @@ private Q_SLOTS: Qt3DRender::QViewport *viewport = new Qt3DRender::QViewport(); Qt3DRender::QClearBuffers *clearBuffer = new Qt3DRender::QClearBuffers(viewport); Qt3DRender::TestAspect testAspect(buildSimpleScene(viewport)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + Qt3DRender::Render::OpenGL::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(clearBuffer->id()); @@ -528,7 +528,7 @@ private Q_SLOTS: { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); @@ -552,7 +552,7 @@ private Q_SLOTS: } { // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); @@ -598,7 +598,7 @@ private Q_SLOTS: QVERIFY(leafNode != nullptr); // WHEN - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); @@ -622,7 +622,7 @@ private Q_SLOTS: Qt3DRender::QLayer *layer = new Qt3DRender::QLayer(); layerFilter->addLayer(layer); Qt3DRender::TestAspect testAspect(buildEntityFilterTestScene(viewport, layer)); - Qt3DRender::Render::Renderer *renderer = testAspect.renderer(); + Qt3DRender::Render::OpenGL::Renderer *renderer = testAspect.renderer(); // THEN Qt3DRender::Render::FrameGraphNode *leafNode = testAspect.nodeManagers()->frameGraphManager()->lookupNode(layerFilter->id()); @@ -631,7 +631,8 @@ private Q_SLOTS: // WHEN renderer->markDirty(Qt3DRender::Render::AbstractRenderer::AllDirty, nullptr); - Qt3DRender::Render::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + Qt3DRender::Render::OpenGL::RenderViewBuilder renderViewBuilder(leafNode, 0, testAspect.renderer()); + renderViewBuilder.setLayerCacheNeedsToBeRebuilt(true); renderViewBuilder.prepareJobs(); renderViewBuilder.buildJobHierachy(); @@ -653,7 +654,7 @@ private Q_SLOTS: std::sort(renderableEntity.begin(), renderableEntity.end()); // WHEN - renderableEntity = Qt3DRender::Render::RenderViewBuilder::entitiesInSubset(renderableEntity, filteredEntity); + renderableEntity = Qt3DRender::Render::OpenGL::RenderViewBuilder::entitiesInSubset(renderableEntity, filteredEntity); // THEN QCOMPARE(renderableEntity.size(), 100); diff --git a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp index d30b8ddca..0b1e22909 100644 --- a/tests/auto/render/opengl/renderviews/tst_renderviews.cpp +++ b/tests/auto/render/opengl/renderviews/tst_renderviews.cpp @@ -48,6 +48,8 @@ namespace Qt3DRender { namespace Render { +namespace OpenGL { + namespace { void compareShaderParameterPacks(const ShaderParameterPack &t1, @@ -127,7 +129,7 @@ private Q_SLOTS: QCOMPARE(backendBarrier.waitOperations(), barriers); // WHEN - Qt3DRender::Render::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); + Qt3DRender::Render::OpenGL::setRenderViewConfigFromFrameGraphLeafNode(&renderView, &backendBarrier); // THEN QCOMPARE(backendBarrier.waitOperations(), renderView.memoryBarrier()); @@ -139,7 +141,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; @@ -174,7 +176,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; @@ -266,7 +268,7 @@ private Q_SLOTS: QFETCH(QVector, expectedMinimizedParameters); Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(&nodeManagers); GLShaderManager *shaderManager = renderer.glResourceManagers()->glShaderManager(); @@ -312,7 +314,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; @@ -347,7 +349,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; @@ -382,7 +384,7 @@ private Q_SLOTS: { // GIVEN Qt3DRender::Render::NodeManagers nodeManagers; - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); RenderView renderView; QVector rawCommands; QVector sortTypes; @@ -542,6 +544,8 @@ private Q_SLOTS: private: }; +} // OpenGL + } // Render } // Qt3DRender @@ -549,6 +553,6 @@ private: QT_END_NAMESPACE //APPLESS_ -QTEST_MAIN(Qt3DRender::Render::tst_RenderViews) +QTEST_MAIN(Qt3DRender::Render::OpenGL::tst_RenderViews) #include "tst_renderviews.moc" diff --git a/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp index 8a345d840..6b714b9e1 100644 --- a/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp +++ b/tests/auto/render/opengl/renderviewutils/tst_renderviewutils.cpp @@ -108,11 +108,11 @@ public: return m_scalar; } - QHash buildUniformMap(const QString &blockName) + QHash buildUniformMap(const QString &blockName) { - QHash uniforms; + QHash uniforms; - uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); return uniforms; } @@ -149,11 +149,11 @@ public: return m_texture; } - QHash buildUniformMap(const QString &blockName) + QHash buildUniformMap(const QString &blockName) { - QHash uniforms; + QHash uniforms; - uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".texture"), Qt3DRender::Render::OpenGL::ShaderUniform()); return uniforms; } @@ -190,11 +190,11 @@ public: return m_array; } - QHash buildUniformMap(const QString &blockName) + QHash buildUniformMap(const QString &blockName) { - QHash uniforms; + QHash uniforms; - uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::OpenGL::ShaderUniform()); return uniforms; } @@ -245,12 +245,12 @@ public: return m_array; } - virtual QHash buildUniformMap(const QString &blockName) + virtual QHash buildUniformMap(const QString &blockName) { - QHash uniforms; + QHash uniforms; - uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::ShaderUniform()); - uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); + uniforms.insert(blockName + QStringLiteral(".array[0]"), Qt3DRender::Render::OpenGL::ShaderUniform()); return uniforms; } @@ -299,17 +299,17 @@ public: return m_inner; } - QHash buildUniformMap(const QString &blockName) override + QHash buildUniformMap(const QString &blockName) override { - QHash innerUniforms; + QHash innerUniforms; StructShaderData *innerData = nullptr; if ((innerData = qobject_cast(m_inner)) != nullptr) innerUniforms = innerData->buildUniformMap(QStringLiteral(".inner")); - QHash uniforms = StructShaderData::buildUniformMap(blockName); - QHash::const_iterator it = innerUniforms.begin(); - const QHash::const_iterator end = innerUniforms.end(); + QHash uniforms = StructShaderData::buildUniformMap(blockName); + QHash::const_iterator it = innerUniforms.begin(); + const QHash::const_iterator end = innerUniforms.end(); while (it != end) { uniforms.insert(blockName + it.key(), it.value()); @@ -362,7 +362,7 @@ void tst_RenderViewUtils::topLevelScalarValueNoUniforms() QVERIFY(backendShaderData != nullptr); // WHEB - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -391,7 +391,7 @@ void tst_RenderViewUtils::topLevelScalarValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -404,8 +404,8 @@ void tst_RenderViewUtils::topLevelScalarValue() QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { // THEN @@ -433,7 +433,7 @@ void tst_RenderViewUtils::topLevelTextureValueNoUniforms() QVERIFY(backendShaderData != nullptr); // WHEB - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -464,7 +464,7 @@ void tst_RenderViewUtils::topLevelTextureValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -477,8 +477,8 @@ void tst_RenderViewUtils::topLevelTextureValue() QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { // THEN @@ -506,7 +506,7 @@ void tst_RenderViewUtils::topLevelArrayValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -519,8 +519,8 @@ void tst_RenderViewUtils::topLevelArrayValue() QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), 1); // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { // THEN @@ -571,13 +571,13 @@ void tst_RenderViewUtils::nestedShaderDataValue() QVERIFY(backendShaderData3 != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[1].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[2].scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendArrayShaderData, QStringLiteral("MyBlock")); @@ -647,7 +647,7 @@ void tst_RenderViewUtils::topLevelStructValue() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; @@ -660,8 +660,8 @@ void tst_RenderViewUtils::topLevelStructValue() QCOMPARE(blockBuilder.activeUniformNamesToValue.count(), blockBuilder.uniforms.count()); // WHEN - Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); - const Qt3DRender::Render::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); + Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator it = blockBuilder.activeUniformNamesToValue.begin(); + const Qt3DRender::Render::OpenGL::UniformBlockValueBuilderHash::const_iterator end = blockBuilder.activeUniformNamesToValue.end(); while (it != end) { // THEN @@ -693,13 +693,13 @@ void tst_RenderViewUtils::topLevelDynamicProperties() QVERIFY(backendShaderData != nullptr); // WHEN - Qt3DRender::Render::UniformBlockValueBuilder blockBuilder; + Qt3DRender::Render::OpenGL::UniformBlockValueBuilder blockBuilder; blockBuilder.shaderDataManager = manager.data(); blockBuilder.textureManager = textureManager.data(); blockBuilder.updatedPropertiesOnly = false; - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::ShaderUniform()); - blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.scalar"), Qt3DRender::Render::OpenGL::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.array[0]"), Qt3DRender::Render::OpenGL::ShaderUniform()); + blockBuilder.uniforms.insert(QStringLiteral("MyBlock.texture"), Qt3DRender::Render::OpenGL::ShaderUniform()); // build name-value map blockBuilder.buildActiveUniformNameValueMapStructHelper(backendShaderData, QStringLiteral("MyBlock")); diff --git a/tests/auto/render/opengl/textures/tst_textures.cpp b/tests/auto/render/opengl/textures/tst_textures.cpp index 984d49a3e..5343a6fde 100644 --- a/tests/auto/render/opengl/textures/tst_textures.cpp +++ b/tests/auto/render/opengl/textures/tst_textures.cpp @@ -222,7 +222,7 @@ private Q_SLOTS: { QSKIP("Texture Sharing is now disabled"); QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(mgrs.data()); // GIVEN @@ -250,7 +250,7 @@ private Q_SLOTS: void shouldCreateDifferentGLTexturess() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(mgrs.data()); // GIVEN @@ -281,7 +281,7 @@ private Q_SLOTS: QVERIFY(renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[i]->peerId()) != renderer.glResourceManagers()->glTextureManager()->lookupResource(backend[k]->peerId())); - QVector glTextures; + QVector glTextures; for (Qt3DRender::Render::Texture *t : backend) glTextures.push_back(renderer.glResourceManagers()->glTextureManager()->lookupResource(t->peerId())); @@ -306,10 +306,10 @@ private Q_SLOTS: void shouldCreateDifferentGLTexturesWhenUsingSharedTextureIds() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(mgrs.data()); - Qt3DRender::Render::GLResourceManagers *glMgrs = renderer.glResourceManagers(); + Qt3DRender::Render::OpenGL::GLResourceManagers *glMgrs = renderer.glResourceManagers(); // both texture having the same sharedTextureId { @@ -335,8 +335,8 @@ private Q_SLOTS: renderer.updateTexture(bt2); // THEN - Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); + Qt3DRender::Render::OpenGL::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::OpenGL::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); QVERIFY(glt1 != glt2); QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); @@ -366,8 +366,8 @@ private Q_SLOTS: renderer.updateTexture(bt2); // THEN - Qt3DRender::Render::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); - Qt3DRender::Render::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); + Qt3DRender::Render::OpenGL::GLTexture *glt1 = glMgrs->glTextureManager()->lookupResource(bt1->peerId()); + Qt3DRender::Render::OpenGL::GLTexture *glt2 = glMgrs->glTextureManager()->lookupResource(bt2->peerId()); QVERIFY(glt1 != glt2); QCOMPARE(glt1->sharedTextureId(), bt1->sharedTextureId()); QCOMPARE(glt2->sharedTextureId(), bt2->sharedTextureId()); @@ -379,7 +379,7 @@ private Q_SLOTS: void generatorsShouldCreateSameData() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); renderer.setNodeManagers(mgrs.data()); // GIVEN @@ -438,7 +438,7 @@ private Q_SLOTS: void checkTextureImageCleanupState() { // GIVEN - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); TestTextureImage img(1); img.setLayer(2); img.setMipLevel(3); @@ -462,7 +462,7 @@ private Q_SLOTS: void checkTextureImageInitializeFromPeer() { // GIVEN - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); TestTextureImage img(1); { @@ -594,7 +594,7 @@ private Q_SLOTS: void checkTextureImageProperlyReleaseGenerator() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); renderer.setNodeManagers(mgrs.data()); @@ -634,7 +634,7 @@ private Q_SLOTS: void checkTextureIsMarkedForDeletion() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); renderer.setNodeManagers(mgrs.data()); @@ -668,7 +668,7 @@ private Q_SLOTS: void checkTextureDestructionReconstructionWithinSameLoop() { QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); renderer.setNodeManagers(mgrs.data()); @@ -707,7 +707,7 @@ private Q_SLOTS: { // GIVEN QScopedPointer mgrs(new Qt3DRender::Render::NodeManagers()); - Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); + Qt3DRender::Render::OpenGL::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous); Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager(); Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager(); renderer.setNodeManagers(mgrs.data()); diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp index 87689e46c..85b5e8c89 100644 --- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp +++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp @@ -87,32 +87,32 @@ namespace Qt3DRender { QVector worldTransformJob() { - static_cast(d_func()->m_renderer)->m_worldTransformJob->setRoot(d_func()->m_renderer->sceneRoot()); - return QVector() << static_cast(d_func()->m_renderer)->m_worldTransformJob; + static_cast(d_func()->m_renderer)->m_worldTransformJob->setRoot(d_func()->m_renderer->sceneRoot()); + return QVector() << static_cast(d_func()->m_renderer)->m_worldTransformJob; } QVector updateBoundingJob() { - static_cast(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob->setManager(d_func()->m_renderer->nodeManagers()->renderNodesManager()); - return QVector() << static_cast(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob; + static_cast(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob->setManager(d_func()->m_renderer->nodeManagers()->renderNodesManager()); + return QVector() << static_cast(d_func()->m_renderer)->m_updateWorldBoundingVolumeJob; } QVector calculateBoundingVolumeJob() { - static_cast(d_func()->m_renderer)->m_calculateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); - return QVector() << static_cast(d_func()->m_renderer)->m_calculateBoundingVolumeJob; + static_cast(d_func()->m_renderer)->m_calculateBoundingVolumeJob->setRoot(d_func()->m_renderer->sceneRoot()); + return QVector() << static_cast(d_func()->m_renderer)->m_calculateBoundingVolumeJob; } QVector framePreparationJob() { - static_cast(d_func()->m_renderer)->m_updateShaderDataTransformJob->setManagers(d_func()->m_renderer->nodeManagers()); - return QVector() << static_cast(d_func()->m_renderer)->m_updateShaderDataTransformJob; + static_cast(d_func()->m_renderer)->m_updateShaderDataTransformJob->setManagers(d_func()->m_renderer->nodeManagers()); + return QVector() << static_cast(d_func()->m_renderer)->m_updateShaderDataTransformJob; } QVector frameCleanupJob() { - static_cast(d_func()->m_renderer)->m_cleanupJob->setRoot(d_func()->m_renderer->sceneRoot()); - return QVector() << static_cast(d_func()->m_renderer)->m_cleanupJob; + static_cast(d_func()->m_renderer)->m_cleanupJob->setRoot(d_func()->m_renderer->sceneRoot()); + return QVector() << static_cast(d_func()->m_renderer)->m_cleanupJob; } QVector renderBinJobs() @@ -140,7 +140,7 @@ namespace Qt3DRender { for (const auto &node: nodes) d_func()->createBackendNode(node); - static_cast(d_func()->m_renderer)->m_renderSceneRoot = + static_cast(d_func()->m_renderer)->m_renderSceneRoot = d_func()->m_renderer->nodeManagers() ->lookupResource(root->id()); } diff --git a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp index 644c4d74c..340bfdda4 100644 --- a/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp +++ b/tests/benchmarks/render/materialparametergathering/tst_bench_materialparametergathering.cpp @@ -90,9 +90,9 @@ public: return d_func()->m_renderer->nodeManagers(); } - Render::MaterialParameterGathererJobPtr materialGathererJob() const + Render::OpenGL::MaterialParameterGathererJobPtr materialGathererJob() const { - Render::MaterialParameterGathererJobPtr job = Render::MaterialParameterGathererJobPtr::create(); + Render::OpenGL::MaterialParameterGathererJobPtr job = Render::OpenGL::MaterialParameterGathererJobPtr::create(); job->setNodeManagers(nodeManagers()); return job; } @@ -136,7 +136,7 @@ private Q_SLOTS: QScopedPointer aspect(new Qt3DRender::TestAspect(buildTestScene(2000))); // WHEN - Qt3DRender::Render::MaterialParameterGathererJobPtr gatheringJob = aspect->materialGathererJob(); + Qt3DRender::Render::OpenGL::MaterialParameterGathererJobPtr gatheringJob = aspect->materialGathererJob(); gatheringJob->setHandles(aspect->nodeManagers()->materialManager()->activeHandles()); QBENCHMARK { -- cgit v1.2.3 From 0159963cf5072e05d068fd7a9b58085ac70021c1 Mon Sep 17 00:00:00 2001 From: Mike Krus Date: Mon, 3 Feb 2020 16:39:14 +0000 Subject: Remove QtGui module path from OpenGL related paths Many are moving to opengl module in qt6, will make merging easier. Change-Id: I0ad08510e6999a5d887d9197fe2cb0dc21919fb9 Reviewed-by: Paul Lemire --- tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp | 2 +- tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp | 2 +- tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp b/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp index 973a1d613..838e5dea9 100644 --- a/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp +++ b/tests/auto/extras/qcuboidgeometry/tst_qcuboidgeometry.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp b/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp index 28fe76ae9..bf5651c9c 100644 --- a/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp +++ b/tests/auto/extras/qtorusgeometry/tst_qtorusgeometry.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp index bbc5219f8..ea14c27bb 100644 --- a/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp +++ b/tests/auto/render/qgraphicsapifilter/tst_qgraphicsapifilter.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include -- cgit v1.2.3 From a054e92ba05a32d13b91908597618b43709c5f68 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 6 Feb 2020 06:46:21 +0100 Subject: tst_qresoucemanager: add test to make sure cleanup is working Change-Id: I5006778b74fee6d030f65deaba86bb38a7a0a86b Reviewed-by: Mike Krus --- .../core/qresourcemanager/tst_qresourcemanager.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'tests') diff --git a/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp b/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp index 9a387a919..a41ea83b5 100644 --- a/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp +++ b/tests/auto/core/qresourcemanager/tst_qresourcemanager.cpp @@ -50,6 +50,7 @@ private slots: void heavyDutyMultiThreadedAccessRelease(); void collectResources(); void activeHandles(); + void checkCleanup(); }; class tst_ArrayResource @@ -422,6 +423,26 @@ void tst_QResourceManager::activeHandles() } } +void tst_QResourceManager::checkCleanup() +{ + // GIVEN + Qt3DCore::QResourceManager manager; + + // WHEN + tHandle newHandle = manager.getOrAcquireHandle(883U); + tst_ArrayResource *data = manager.data(newHandle); + + data->m_value.ref(); + // THEN + QCOMPARE(data->m_value.load(), 1); + + // WHEN + manager.release(newHandle); + + // THEN + QCOMPARE(data->m_value.load(), 0); +} + -- cgit v1.2.3