From a555bd4316b1f1dd387ec66c3e6de53b78058a62 Mon Sep 17 00:00:00 2001
From: Tomi Korpipaa <tomi.korpipaa@qt.io>
Date: Fri, 26 Jun 2020 10:50:58 +0300
Subject: [PATCH] WIP: Add comparisonKey to QSGTexture

This is an implementation of comparisonKey for 5.12 that does not
require QRhi like it does in 5.14.

Task-number: QTBUG-84401
Change-Id: I664def07d95b9f30a6f7f373ef5db0669c78c34a
---
 examples/quick/textureprovider/etcprovider.cpp      | 11 +++++++++++
 examples/quick/textureprovider/etcprovider.h        |  1 +
 src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp      |  8 ++++++++
 src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h      |  1 +
 src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp    | 11 +++++++++++
 src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h    |  1 +
 .../adaptations/software/qsgsoftwarelayer.cpp       |  5 +++++
 .../adaptations/software/qsgsoftwarelayer_p.h       |  1 +
 .../software/qsgsoftwarepixmaptexture.cpp           |  5 +++++
 .../software/qsgsoftwarepixmaptexture_p.h           |  1 +
 .../compressedtexture/qsgcompressedtexture.cpp      |  8 ++++++++
 .../compressedtexture/qsgcompressedtexture_p.h      |  1 +
 src/quick/scenegraph/qsgdefaultlayer.cpp            |  5 +++++
 src/quick/scenegraph/qsgdefaultlayer_p.h            |  1 +
 src/quick/scenegraph/util/qsgatlastexture.cpp       |  7 +++++++
 src/quick/scenegraph/util/qsgatlastexture_p.h       |  1 +
 src/quick/scenegraph/util/qsgtexture.cpp            | 13 +++++++++++++
 src/quick/scenegraph/util/qsgtexture.h              |  1 +
 src/quick/scenegraph/util/qsgtexture_p.h            |  1 +
 src/quick/scenegraph/util/qsgtexturematerial.cpp    | 11 ++++++++---
 20 files changed, 91 insertions(+), 3 deletions(-)

diff --git a/examples/quick/textureprovider/etcprovider.cpp b/examples/quick/textureprovider/etcprovider.cpp
index 65960169e2..6468c627b0 100644
--- a/examples/quick/textureprovider/etcprovider.cpp
+++ b/examples/quick/textureprovider/etcprovider.cpp
@@ -116,6 +116,17 @@ int EtcTexture::textureId() const
     return m_texture_id;
 }
 
+int EtcTexture::comparisonKey() const
+{
+    if (m_texture_id)
+        return m_texture_id;
+
+    if (!m_data.isNull())
+        return int(qintptr(m_data.data()));
+
+    return int(qintptr(this));
+}
+
 void EtcTexture::bind()
 {
     if (m_uploaded && m_texture_id) {
diff --git a/examples/quick/textureprovider/etcprovider.h b/examples/quick/textureprovider/etcprovider.h
index 44d5d6f53e..a9bace7719 100644
--- a/examples/quick/textureprovider/etcprovider.h
+++ b/examples/quick/textureprovider/etcprovider.h
@@ -82,6 +82,7 @@ public:
 
     QSize textureSize() const { return m_size; }
     int textureId() const;
+    int comparisonKey() const override;
 
     bool hasAlphaChannel() const { return false; }
     bool hasMipmaps() const { return false; }
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp
index faa6f7566a..67cff72b02 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12layer.cpp
@@ -79,6 +79,14 @@ QSize QSGD3D12Layer::textureSize() const
     return m_size;
 }
 
+int QSGD3D12Layer::comparisonKey() const
+{
+    if (m_rt)
+        return m_rt;
+
+    return int(qintptr(this));
+}
+
 bool QSGD3D12Layer::hasAlphaChannel() const
 {
     return true;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
index f828843227..08976a5bdf 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12layer_p.h
@@ -67,6 +67,7 @@ public:
 
     int textureId() const override;
     QSize textureSize() const override;
+    int comparisonKey() const override;
     bool hasAlphaChannel() const override;
     bool hasMipmaps() const override;
     QRectF normalizedTextureSubRect() const override;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp b/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp
index a5f3eb7a31..ad2f4e68ff 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12texture.cpp
@@ -85,6 +85,17 @@ QSize QSGD3D12Texture::textureSize() const
     return m_image.size();
 }
 
+int QSGD3D12Texture::comparisonKey() const
+{
+    if (m_id)
+        return m_id;
+
+    if (!m_image.isNull())
+        return int(qintptr(m_image.bits()));
+
+    return int(qintptr(this));
+}
+
 bool QSGD3D12Texture::hasAlphaChannel() const
 {
     return m_alphaWanted;
diff --git a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h b/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h
index 3d0e226ddb..3a1da8bc55 100644
--- a/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h
+++ b/src/plugins/scenegraph/d3d12/qsgd3d12texture_p.h
@@ -68,6 +68,7 @@ public:
 
     int textureId() const override;
     QSize textureSize() const override;
+    int comparisonKey() const override;
     bool hasAlphaChannel() const override;
     bool hasMipmaps() const override;
     QRectF normalizedTextureSubRect() const override;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
index 70378d2950..5393e3bc0f 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
@@ -69,6 +69,11 @@ int QSGSoftwareLayer::textureId() const
     return 0;
 }
 
+int QSGSoftwareLayer::comparisonKey() const
+{
+    return int(qintptr(this));
+}
+
 QSize QSGSoftwareLayer::textureSize() const
 {
     return m_pixmap.size();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
index 9f5a22e66f..8b9d4120a9 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer_p.h
@@ -74,6 +74,7 @@ public:
     bool hasAlphaChannel() const override;
     bool hasMipmaps() const override;
     void bind() override;
+    int comparisonKey() const override;
 
     // QSGDynamicTexture interface
 public:
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture.cpp
index 16e3a111ae..022f73e88d 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture.cpp
@@ -65,6 +65,11 @@ int QSGSoftwarePixmapTexture::textureId() const
     return 0;
 }
 
+int QSGSoftwarePixmapTexture::comparisonKey() const
+{
+    return int(qintptr(this));
+}
+
 QSize QSGSoftwarePixmapTexture::textureSize() const
 {
     return m_pixmap.size();
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture_p.h
index 034fa25da9..1b383cff89 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaptexture_p.h
@@ -66,6 +66,7 @@ public:
     QSize textureSize() const override;
     bool hasAlphaChannel() const override;
     bool hasMipmaps() const override;
+    int comparisonKey() const override;
     void bind() override;
 
     const QPixmap &pixmap() const { return m_pixmap; }
diff --git a/src/quick/scenegraph/compressedtexture/qsgcompressedtexture.cpp b/src/quick/scenegraph/compressedtexture/qsgcompressedtexture.cpp
index d3310bc11c..72b62897db 100644
--- a/src/quick/scenegraph/compressedtexture/qsgcompressedtexture.cpp
+++ b/src/quick/scenegraph/compressedtexture/qsgcompressedtexture.cpp
@@ -85,6 +85,14 @@ int QSGCompressedTexture::textureId() const
     return m_textureId;
 }
 
+int QSGCompressedTexture::comparisonKey() const
+{
+    if (m_textureId)
+        return m_textureId;
+
+    return int(qintptr(this));
+ }
+
 QSize QSGCompressedTexture::textureSize() const
 {
     return m_size;
diff --git a/src/quick/scenegraph/compressedtexture/qsgcompressedtexture_p.h b/src/quick/scenegraph/compressedtexture/qsgcompressedtexture_p.h
index c3b58a2389..b180135c6e 100644
--- a/src/quick/scenegraph/compressedtexture/qsgcompressedtexture_p.h
+++ b/src/quick/scenegraph/compressedtexture/qsgcompressedtexture_p.h
@@ -70,6 +70,7 @@ public:
     QSize textureSize() const override;
     bool hasAlphaChannel() const override;
     bool hasMipmaps() const override;
+    int comparisonKey() const override;
 
     void bind() override;
 
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index b2b123912f..95417affb4 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -141,6 +141,11 @@ int QSGDefaultLayer::textureId() const
     return m_fbo ? m_fbo->texture() : 0;
 }
 
+int QSGDefaultLayer::comparisonKey() const
+{
+    return int(qintptr(this));
+}
+
 bool QSGDefaultLayer::hasAlphaChannel() const
 {
     return m_format != GL_RGB;
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index 06355e0c21..9c5b252951 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -89,6 +89,7 @@ public:
     bool hasMipmaps() const override;
     int textureId() const override;
     QSize textureSize() const override { return m_size; }
+    int comparisonKey() const override;
 
     GLenum format() const { return m_format; }
     void setFormat(GLenum format) override;
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 921ed0c1fc..569ca5f43e 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -506,6 +506,13 @@ TextureBase::~TextureBase()
     m_atlas->remove(this);
 }
 
+int TextureBase::comparisonKey() const {
+    if (m_atlas->textureId())
+        return m_atlas->textureId();
+
+    return int(qintptr(this));
+}
+
 void TextureBase::bind()
 {
     m_atlas->bind(filtering());
diff --git a/src/quick/scenegraph/util/qsgatlastexture_p.h b/src/quick/scenegraph/util/qsgatlastexture_p.h
index 14dc8f7958..437e21729a 100644
--- a/src/quick/scenegraph/util/qsgatlastexture_p.h
+++ b/src/quick/scenegraph/util/qsgatlastexture_p.h
@@ -160,6 +160,7 @@ public:
 
     int textureId() const override { return m_atlas->textureId(); }
     bool isAtlasTexture() const override { return true; }
+    int comparisonKey() const override;
 
     QRect atlasSubRect() const { return m_allocated_rect; }
 
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index d33bdffe74..ca09ca5e19 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -701,6 +701,19 @@ void QSGPlainTexture::setTextureId(int id)
     m_mipmaps_generated = false;
 }
 
+int QSGPlainTexture::comparisonKey() const
+{
+    // not textureId() as that would create an id when not yet done - that's not wanted here
+    if (m_texture_id)
+        return m_texture_id;
+
+    if (!m_image.isNull())
+        return int(qintptr(m_image.bits()));
+
+    // two textures (and so materials) with not-yet-created texture underneath are never equal
+    return int(qintptr(this));
+}
+
 void QSGPlainTexture::bind()
 {
 #if QT_CONFIG(opengl)
diff --git a/src/quick/scenegraph/util/qsgtexture.h b/src/quick/scenegraph/util/qsgtexture.h
index 7bd57a16e3..648fe955b1 100644
--- a/src/quick/scenegraph/util/qsgtexture.h
+++ b/src/quick/scenegraph/util/qsgtexture.h
@@ -80,6 +80,7 @@ public:
     virtual QSize textureSize() const = 0;
     virtual bool hasAlphaChannel() const = 0;
     virtual bool hasMipmaps() const = 0;
+    virtual int comparisonKey() const = 0;
 
     virtual QRectF normalizedTextureSubRect() const;
 
diff --git a/src/quick/scenegraph/util/qsgtexture_p.h b/src/quick/scenegraph/util/qsgtexture_p.h
index 18dd5eff68..35630bd05e 100644
--- a/src/quick/scenegraph/util/qsgtexture_p.h
+++ b/src/quick/scenegraph/util/qsgtexture_p.h
@@ -92,6 +92,7 @@ public:
     int textureId() const override;
     void setTextureSize(const QSize &size) { m_texture_size = size; }
     QSize textureSize() const override { return m_texture_size; }
+    int comparisonKey() const override;
 
     void setHasAlphaChannel(bool alpha) { m_has_alpha = alpha; }
     bool hasAlphaChannel() const override { return m_has_alpha; }
diff --git a/src/quick/scenegraph/util/qsgtexturematerial.cpp b/src/quick/scenegraph/util/qsgtexturematerial.cpp
index 7b1d5abb26..bb792fd36a 100644
--- a/src/quick/scenegraph/util/qsgtexturematerial.cpp
+++ b/src/quick/scenegraph/util/qsgtexturematerial.cpp
@@ -323,13 +323,18 @@ int QSGOpaqueTextureMaterial::compare(const QSGMaterial *o) const
 {
     Q_ASSERT(o && type() == o->type());
     const QSGOpaqueTextureMaterial *other = static_cast<const QSGOpaqueTextureMaterial *>(o);
-    if (int diff = m_texture->textureId() - other->texture()->textureId())
-        return diff;
+    int tid1 = m_texture->comparisonKey();
+    int tid2 = other->texture()->comparisonKey();
+    if (tid1 != tid2)
+        return tid1 - tid2;
+
+    if ((tid1 == 0 && tid2 == 0) && m_texture != other->m_texture)
+        return 1;
+
     return int(m_filtering) - int(other->m_filtering);
 }
 
 
-
 /*!
     \class QSGTextureMaterial
     \brief The QSGTextureMaterial class provides a convenient way of
-- 
2.17.1

