| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the Qt3D module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 | #include <QtTest/QTest> | 
| 30 | #include <qbackendnodetester.h> | 
| 31 | #include <Qt3DRender/private/texture_p.h> | 
| 32 |  | 
| 33 | #include "testpostmanarbiter.h" | 
| 34 | #include "testrenderer.h" | 
| 35 |  | 
| 36 | class DummyTexture : public Qt3DRender::QAbstractTexture | 
| 37 | { | 
| 38 |     Q_OBJECT | 
| 39 |  | 
| 40 | public: | 
| 41 |     explicit DummyTexture(Qt3DCore::QNode *parent = nullptr) | 
| 42 |         : QAbstractTexture(TargetAutomatic, parent) | 
| 43 |     { | 
| 44 |     } | 
| 45 | }; | 
| 46 |  | 
| 47 | class FakeGenerator : public Qt3DRender::QTextureGenerator | 
| 48 | { | 
| 49 | public: | 
| 50 |     QT3D_FUNCTOR(FakeGenerator) | 
| 51 |  | 
| 52 |     Qt3DRender::QTextureDataPtr operator ()() override | 
| 53 |     { | 
| 54 |         return {}; | 
| 55 |     } | 
| 56 |  | 
| 57 |     bool operator ==(const QTextureGenerator &) const override | 
| 58 |     { | 
| 59 |         return true; | 
| 60 |     } | 
| 61 | }; | 
| 62 |  | 
| 63 | class tst_RenderTexture : public Qt3DCore::QBackendNodeTester | 
| 64 | { | 
| 65 |     Q_OBJECT | 
| 66 |  | 
| 67 | private: | 
| 68 |     template <typename FrontendTextureType, Qt3DRender::QAbstractTexture::Target Target> | 
| 69 |     void checkPropertyMirroring(); | 
| 70 |  | 
| 71 | private slots: | 
| 72 |     void checkDefaults(); | 
| 73 |     void checkFrontendPropertyNotifications(); | 
| 74 |     void checkPropertyMirroring(); | 
| 75 |     void checkPropertyChanges(); | 
| 76 |     void checkTextureImageBookeeping(); | 
| 77 |     void checkInitialUpdateData(); | 
| 78 | }; | 
| 79 |  | 
| 80 | void tst_RenderTexture::checkDefaults() | 
| 81 | { | 
| 82 |     Qt3DRender::Render::Texture backend; | 
| 83 |  | 
| 84 |     QCOMPARE(backend.properties().format, Qt3DRender::QAbstractTexture::NoFormat); | 
| 85 |     QCOMPARE(backend.properties().width, 1); | 
| 86 |     QCOMPARE(backend.properties().height, 1); | 
| 87 |     QCOMPARE(backend.properties().depth, 1); | 
| 88 |     QCOMPARE(backend.properties().layers, 1); | 
| 89 |     QCOMPARE(backend.properties().mipLevels, 1); | 
| 90 |     QCOMPARE(backend.properties().samples, 1); | 
| 91 |     QCOMPARE(backend.properties().generateMipMaps, false); | 
| 92 |     QCOMPARE(backend.parameters().magnificationFilter, Qt3DRender::QAbstractTexture::Nearest); | 
| 93 |     QCOMPARE(backend.parameters().minificationFilter, Qt3DRender::QAbstractTexture::Nearest); | 
| 94 |     QCOMPARE(backend.parameters().wrapModeX, Qt3DRender::QTextureWrapMode::ClampToEdge); | 
| 95 |     QCOMPARE(backend.parameters().wrapModeY, Qt3DRender::QTextureWrapMode::ClampToEdge); | 
| 96 |     QCOMPARE(backend.parameters().wrapModeZ, Qt3DRender::QTextureWrapMode::ClampToEdge); | 
| 97 |     QCOMPARE(backend.parameters().maximumAnisotropy, 1.0f); | 
| 98 |     QCOMPARE(backend.parameters().comparisonFunction, Qt3DRender::QAbstractTexture::CompareLessEqual); | 
| 99 |     QCOMPARE(backend.parameters().comparisonMode, Qt3DRender::QAbstractTexture::CompareNone); | 
| 100 | } | 
| 101 |  | 
| 102 | void tst_RenderTexture::checkFrontendPropertyNotifications() | 
| 103 | { | 
| 104 |     // GIVEN | 
| 105 |     TestArbiter arbiter; | 
| 106 |     DummyTexture texture; | 
| 107 |     arbiter.setArbiterOnNode(&texture); | 
| 108 |  | 
| 109 |     // WHEN | 
| 110 |     texture.setWidth(512); | 
| 111 |     QCoreApplication::processEvents(); | 
| 112 |  | 
| 113 |     // THEN | 
| 114 |     QCOMPARE(arbiter.events.size(), 0); | 
| 115 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 116 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 117 |  | 
| 118 |     arbiter.dirtyNodes.clear(); | 
| 119 |  | 
| 120 |     // WHEN | 
| 121 |     texture.setWidth(512); | 
| 122 |     QCoreApplication::processEvents(); | 
| 123 |  | 
| 124 |     // THEN | 
| 125 |     QCOMPARE(arbiter.events.size(), 0); | 
| 126 |     QCOMPARE(arbiter.dirtyNodes.size(), 0); | 
| 127 |  | 
| 128 |     // WHEN | 
| 129 |     texture.setHeight(256); | 
| 130 |     QCoreApplication::processEvents(); | 
| 131 |  | 
| 132 |     // THEN | 
| 133 |     QCOMPARE(arbiter.events.size(), 0); | 
| 134 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 135 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 136 |  | 
| 137 |     arbiter.dirtyNodes.clear(); | 
| 138 |  | 
| 139 |     // WHEN | 
| 140 |     texture.setHeight(256); | 
| 141 |     QCoreApplication::processEvents(); | 
| 142 |  | 
| 143 |     // THEN | 
| 144 |     QCOMPARE(arbiter.events.size(), 0); | 
| 145 |     QCOMPARE(arbiter.dirtyNodes.size(), 0); | 
| 146 |  | 
| 147 |     // WHEN | 
| 148 |     texture.setDepth(128); | 
| 149 |     QCoreApplication::processEvents(); | 
| 150 |  | 
| 151 |     // THEN | 
| 152 |     QCOMPARE(arbiter.events.size(), 0); | 
| 153 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 154 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 155 |  | 
| 156 |     arbiter.dirtyNodes.clear(); | 
| 157 |  | 
| 158 |     // WHEN | 
| 159 |     texture.setDepth(128); | 
| 160 |     QCoreApplication::processEvents(); | 
| 161 |  | 
| 162 |     // THEN | 
| 163 |     QCOMPARE(arbiter.events.size(), 0); | 
| 164 |     QCOMPARE(arbiter.events.size(), 0); | 
| 165 |  | 
| 166 |     // WHEN | 
| 167 |     texture.setLayers(16); | 
| 168 |     QCoreApplication::processEvents(); | 
| 169 |  | 
| 170 |     // THEN | 
| 171 |     QCOMPARE(arbiter.events.size(), 0); | 
| 172 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 173 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 174 |  | 
| 175 |     arbiter.dirtyNodes.clear(); | 
| 176 |  | 
| 177 |     // WHEN | 
| 178 |     texture.setLayers(16); | 
| 179 |     QCoreApplication::processEvents(); | 
| 180 |  | 
| 181 |     // THEN | 
| 182 |     QCOMPARE(arbiter.events.size(), 0); | 
| 183 |     QCOMPARE(arbiter.dirtyNodes.size(), 0); | 
| 184 |  | 
| 185 |     // WHEN | 
| 186 |     texture.setSamples(32); | 
| 187 |     QCoreApplication::processEvents(); | 
| 188 |  | 
| 189 |     // THEN | 
| 190 |     QCOMPARE(arbiter.events.size(), 0); | 
| 191 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 192 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 193 |  | 
| 194 |     arbiter.dirtyNodes.clear(); | 
| 195 |  | 
| 196 |     // WHEN | 
| 197 |     texture.setSamples(32); | 
| 198 |     QCoreApplication::processEvents(); | 
| 199 |  | 
| 200 |     // THEN | 
| 201 |     QCOMPARE(arbiter.events.size(), 0); | 
| 202 |     QCOMPARE(arbiter.dirtyNodes.size(), 0); | 
| 203 |  | 
| 204 |     // WHEN | 
| 205 |     Qt3DRender::QTextureImage img; | 
| 206 |     texture.addTextureImage(textureImage: &img); | 
| 207 |  | 
| 208 |     // THEN | 
| 209 |     QCOMPARE(arbiter.events.size(), 0); | 
| 210 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 211 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 212 |  | 
| 213 |     arbiter.dirtyNodes.clear(); | 
| 214 |  | 
| 215 |     // WHEN | 
| 216 |     texture.removeTextureImage(textureImage: &img); | 
| 217 |  | 
| 218 |     // THEN | 
| 219 |     QCOMPARE(arbiter.events.size(), 0); | 
| 220 |     QCOMPARE(arbiter.dirtyNodes.size(), 1); | 
| 221 |     QCOMPARE(arbiter.dirtyNodes.front(), &texture); | 
| 222 |  | 
| 223 |     arbiter.dirtyNodes.clear(); | 
| 224 | } | 
| 225 |  | 
| 226 | template <typename FrontendTextureType, Qt3DRender::QAbstractTexture::Target Target> | 
| 227 | void tst_RenderTexture::checkPropertyMirroring() | 
| 228 | { | 
| 229 |     // GIVEN | 
| 230 |     Qt3DRender::Render::Texture backend; | 
| 231 |  | 
| 232 |     FrontendTextureType frontend; | 
| 233 |     frontend.setWidth(256); | 
| 234 |     frontend.setHeight(128); | 
| 235 |     frontend.setDepth(16); | 
| 236 |     frontend.setLayers(8); | 
| 237 |     frontend.setSamples(32); | 
| 238 |  | 
| 239 |     // WHEN | 
| 240 |     simulateInitializationSync(&frontend, &backend); | 
| 241 |  | 
| 242 |     // THEN | 
| 243 |     QCOMPARE(backend.peerId(), frontend.id()); | 
| 244 |     QCOMPARE(backend.properties().target, Target); | 
| 245 |     QCOMPARE(backend.properties().width, frontend.width()); | 
| 246 |     QCOMPARE(backend.properties().height, frontend.height()); | 
| 247 |     QCOMPARE(backend.properties().depth, frontend.depth()); | 
| 248 |     QCOMPARE(backend.properties().layers, frontend.layers()); | 
| 249 |     QCOMPARE(backend.properties().samples, frontend.samples()); | 
| 250 | } | 
| 251 |  | 
| 252 | void tst_RenderTexture::checkPropertyMirroring() | 
| 253 | { | 
| 254 |     checkPropertyMirroring<Qt3DRender::QTexture1D, Qt3DRender::QAbstractTexture::Target1D>(); | 
| 255 |     checkPropertyMirroring<Qt3DRender::QTexture1DArray, Qt3DRender::QAbstractTexture::Target1DArray>(); | 
| 256 |     checkPropertyMirroring<Qt3DRender::QTexture2D, Qt3DRender::QAbstractTexture::Target2D>(); | 
| 257 |     checkPropertyMirroring<Qt3DRender::QTexture2DArray, Qt3DRender::QAbstractTexture::Target2DArray>(); | 
| 258 |     checkPropertyMirroring<Qt3DRender::QTexture3D, Qt3DRender::QAbstractTexture::Target3D>(); | 
| 259 |     checkPropertyMirroring<Qt3DRender::QTextureCubeMap, Qt3DRender::QAbstractTexture::TargetCubeMap>(); | 
| 260 |     checkPropertyMirroring<Qt3DRender::QTextureCubeMapArray, Qt3DRender::QAbstractTexture::TargetCubeMapArray>(); | 
| 261 |     checkPropertyMirroring<Qt3DRender::QTexture2DMultisample, Qt3DRender::QAbstractTexture::Target2DMultisample>(); | 
| 262 |     checkPropertyMirroring<Qt3DRender::QTexture2DMultisampleArray, Qt3DRender::QAbstractTexture::Target2DMultisampleArray>(); | 
| 263 |     checkPropertyMirroring<Qt3DRender::QTextureRectangle, Qt3DRender::QAbstractTexture::TargetRectangle>(); | 
| 264 |     checkPropertyMirroring<Qt3DRender::QTextureBuffer, Qt3DRender::QAbstractTexture::TargetBuffer>(); | 
| 265 | } | 
| 266 |  | 
| 267 | void tst_RenderTexture::checkPropertyChanges() | 
| 268 | { | 
| 269 |     // GIVEN | 
| 270 |     TestRenderer renderer; | 
| 271 |     Qt3DRender::QSharedGLTexture frontend; | 
| 272 |     Qt3DRender::Render::Texture backend; | 
| 273 |     backend.setRenderer(&renderer); | 
| 274 |     backend.unsetDirty(); | 
| 275 |  | 
| 276 |     // WHEN | 
| 277 |     frontend.setWidth(256); | 
| 278 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 279 |  | 
| 280 |     // THEN | 
| 281 |     QCOMPARE(backend.properties().width, 256); | 
| 282 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 283 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 284 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 285 |     backend.unsetDirty(); | 
| 286 |  | 
| 287 |     // WHEN | 
| 288 |     frontend.setHeight(128); | 
| 289 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 290 |  | 
| 291 |     // THEN | 
| 292 |     QCOMPARE(backend.properties().height, 128); | 
| 293 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 294 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 295 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 296 |     backend.unsetDirty(); | 
| 297 |  | 
| 298 |     // WHEN | 
| 299 |     frontend.setDepth(16); | 
| 300 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 301 |  | 
| 302 |     // THEN | 
| 303 |     QCOMPARE(backend.properties().depth, 16); | 
| 304 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 305 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 306 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 307 |     backend.unsetDirty(); | 
| 308 |  | 
| 309 |     // WHEN | 
| 310 |     frontend.setFormat(Qt3DRender::QAbstractTexture::RGB16F); | 
| 311 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 312 |  | 
| 313 |     // THEN | 
| 314 |     QCOMPARE(backend.properties().format, Qt3DRender::QAbstractTexture::RGB16F); | 
| 315 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 316 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 317 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 318 |     backend.unsetDirty(); | 
| 319 |  | 
| 320 |     // WHEN | 
| 321 |     frontend.setGenerateMipMaps(true); | 
| 322 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 323 |  | 
| 324 |     // THEN | 
| 325 |     QCOMPARE(backend.properties().generateMipMaps, true); | 
| 326 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 327 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 328 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 329 |     backend.unsetDirty(); | 
| 330 |  | 
| 331 |     // WHEN | 
| 332 |     frontend.setMinificationFilter(Qt3DRender::QAbstractTexture::LinearMipMapLinear); | 
| 333 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 334 |  | 
| 335 |     // THEN | 
| 336 |     QCOMPARE(backend.parameters().minificationFilter, Qt3DRender::QAbstractTexture::LinearMipMapLinear); | 
| 337 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 338 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 339 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 340 |     backend.unsetDirty(); | 
| 341 |  | 
| 342 |     // WHEN | 
| 343 |     frontend.setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear); | 
| 344 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 345 |  | 
| 346 |     // THEN | 
| 347 |     QCOMPARE(backend.parameters().magnificationFilter, Qt3DRender::QAbstractTexture::Linear); | 
| 348 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 349 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 350 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 351 |     backend.unsetDirty(); | 
| 352 |  | 
| 353 |     // WHEN | 
| 354 |     frontend.wrapMode()->setX(Qt3DRender::QTextureWrapMode::Repeat); | 
| 355 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 356 |  | 
| 357 |     // THEN | 
| 358 |     QCOMPARE(backend.parameters().wrapModeX, Qt3DRender::QTextureWrapMode::Repeat); | 
| 359 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 360 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 361 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 362 |     backend.unsetDirty(); | 
| 363 |  | 
| 364 |     // WHEN | 
| 365 |     frontend.wrapMode()->setY(Qt3DRender::QTextureWrapMode::Repeat); | 
| 366 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 367 |  | 
| 368 |     // THEN | 
| 369 |     QCOMPARE(backend.parameters().wrapModeY, Qt3DRender::QTextureWrapMode::Repeat); | 
| 370 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 371 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 372 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 373 |     backend.unsetDirty(); | 
| 374 |  | 
| 375 |     // WHEN | 
| 376 |     frontend.wrapMode()->setZ(Qt3DRender::QTextureWrapMode::Repeat); | 
| 377 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 378 |  | 
| 379 |     // THEN | 
| 380 |     QCOMPARE(backend.parameters().wrapModeZ, Qt3DRender::QTextureWrapMode::Repeat); | 
| 381 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 382 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 383 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 384 |     backend.unsetDirty(); | 
| 385 |  | 
| 386 |     // WHEN | 
| 387 |     frontend.setMaximumAnisotropy(16.f); | 
| 388 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 389 |  | 
| 390 |     // THEN | 
| 391 |     QCOMPARE(backend.parameters().maximumAnisotropy, 16.0f); | 
| 392 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 393 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 394 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 395 |     backend.unsetDirty(); | 
| 396 |  | 
| 397 |     // WHEN | 
| 398 |     frontend.setComparisonFunction(Qt3DRender::QAbstractTexture::CompareEqual); | 
| 399 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 400 |  | 
| 401 |     // THEN | 
| 402 |     QCOMPARE(backend.parameters().comparisonFunction, Qt3DRender::QAbstractTexture::CompareEqual); | 
| 403 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 404 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 405 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 406 |     backend.unsetDirty(); | 
| 407 |  | 
| 408 |     // WHEN | 
| 409 |     frontend.setComparisonMode(Qt3DRender::QAbstractTexture::CompareRefToTexture); | 
| 410 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 411 |  | 
| 412 |     // THEN | 
| 413 |     QCOMPARE(backend.parameters().comparisonMode, Qt3DRender::QAbstractTexture::CompareRefToTexture); | 
| 414 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 415 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyParameters); | 
| 416 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 417 |     backend.unsetDirty(); | 
| 418 |  | 
| 419 |     // WHEN | 
| 420 |     frontend.setLayers(32); | 
| 421 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 422 |  | 
| 423 |     // THEN | 
| 424 |     QCOMPARE(backend.properties().layers, 32); | 
| 425 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 426 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 427 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 428 |     backend.unsetDirty(); | 
| 429 |  | 
| 430 |     // WHEN | 
| 431 |     frontend.setSamples(64); | 
| 432 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 433 |  | 
| 434 |     // THEN | 
| 435 |     QCOMPARE(backend.properties().samples, 64); | 
| 436 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 437 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyProperties); | 
| 438 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 439 |     backend.unsetDirty(); | 
| 440 |  | 
| 441 |     // WHEN | 
| 442 |     frontend.setTextureId(883); | 
| 443 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 444 |  | 
| 445 |     // THEN | 
| 446 |     QCOMPARE(backend.sharedTextureId(), 883); | 
| 447 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 448 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtySharedTextureId); | 
| 449 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 450 |     backend.unsetDirty(); | 
| 451 |  | 
| 452 |     // WHEN | 
| 453 |     Qt3DRender::QTextureImage img; | 
| 454 |     frontend.addTextureImage(textureImage: &img); | 
| 455 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 456 |  | 
| 457 |     // THEN | 
| 458 |     QCOMPARE(backend.textureImageIds().size(), 1); | 
| 459 |     QCOMPARE(backend.textureImageIds().first(), img.id()); | 
| 460 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 461 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyImageGenerators); | 
| 462 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 463 |     backend.unsetDirty(); | 
| 464 |  | 
| 465 |     // WHEN | 
| 466 |     Qt3DRender::QTextureDataUpdate updateData; | 
| 467 |     updateData.setX(100); | 
| 468 |     updateData.setY(100); | 
| 469 |     updateData.setZ(100); | 
| 470 |     frontend.updateData(update: updateData); | 
| 471 |     backend.syncFromFrontEnd(frontEnd: &frontend, firstTime: false); | 
| 472 |  | 
| 473 |     // THEN | 
| 474 |     const QVector<Qt3DRender::QTextureDataUpdate> pendingUpdates = backend.takePendingTextureDataUpdates(); | 
| 475 |     QCOMPARE(pendingUpdates.size(), 1); | 
| 476 |     QCOMPARE(pendingUpdates.first(), updateData); | 
| 477 |     QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::TexturesDirty); | 
| 478 |     QVERIFY(backend.dirtyFlags() == Qt3DRender::Render::Texture::DirtyPendingDataUpdates); | 
| 479 |     renderer.clearDirtyBits(changes: Qt3DRender::Render::AbstractRenderer::AllDirty); | 
| 480 |     backend.unsetDirty(); | 
| 481 | } | 
| 482 |  | 
| 483 | void tst_RenderTexture::checkTextureImageBookeeping() | 
| 484 | { | 
| 485 |     // GIVEN | 
| 486 |     TestArbiter arbiter; | 
| 487 |     DummyTexture texture; | 
| 488 |     arbiter.setArbiterOnNode(&texture); | 
| 489 |  | 
| 490 |     QCoreApplication::processEvents(); | 
| 491 |  | 
| 492 |     { | 
| 493 |         // WHEN | 
| 494 |         Qt3DRender::QTextureImage img; | 
| 495 |         texture.addTextureImage(textureImage: &img); | 
| 496 |  | 
| 497 |         // THEN | 
| 498 |         QCOMPARE(img.parent(), &texture); | 
| 499 |         QCOMPARE(texture.textureImages().size(), 1); | 
| 500 |         QCOMPARE(texture.textureImages().first()->id(), img.id()); | 
| 501 |     } | 
| 502 |     // WHEN -> img is destroyed | 
| 503 |  | 
| 504 |     // THEN | 
| 505 |     QCOMPARE(texture.textureImages().size(), 0); | 
| 506 | } | 
| 507 |  | 
| 508 | void tst_RenderTexture::checkInitialUpdateData() | 
| 509 | { | 
| 510 |     // GIVEN | 
| 511 |     TestRenderer renderer; | 
| 512 |     DummyTexture frontend; | 
| 513 |     Qt3DRender::Render::Texture backend; | 
| 514 |  | 
| 515 |     backend.setRenderer(&renderer); | 
| 516 |  | 
| 517 |     Qt3DRender::QTextureDataUpdate updateData; | 
| 518 |     updateData.setX(100); | 
| 519 |     updateData.setY(100); | 
| 520 |     updateData.setZ(100); | 
| 521 |  | 
| 522 |     // WHEN -> updateData with no backend/arbiter | 
| 523 |     frontend.updateData(update: updateData); | 
| 524 |     simulateInitializationSync(frontend: &frontend, backend: &backend); | 
| 525 |  | 
| 526 |     // THEN -> should have received the update as part of the initial data | 
| 527 |     const QVector<Qt3DRender::QTextureDataUpdate> pendingUpdates = backend.takePendingTextureDataUpdates(); | 
| 528 |     QCOMPARE(pendingUpdates.size(), 1); | 
| 529 |     QCOMPARE(pendingUpdates.first(), updateData); | 
| 530 |     QVERIFY(backend.dirtyFlags() & Qt3DRender::Render::Texture::DirtyPendingDataUpdates); | 
| 531 | } | 
| 532 |  | 
| 533 | QTEST_APPLESS_MAIN(tst_RenderTexture) | 
| 534 |  | 
| 535 | #include "tst_texture.moc" | 
| 536 |  |