1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsgdefaultinternalimagenode_p.h"
5#include <private/qsgdefaultrendercontext_p.h>
6#include <private/qsgmaterialshader_p.h>
7#include <private/qsgtexturematerial_p.h>
8#include <qopenglfunctions.h>
9#include <QtCore/qmath.h>
10#include <rhi/qrhi.h>
11
12QT_BEGIN_NAMESPACE
13
14class SmoothTextureMaterialRhiShader : public QSGTextureMaterialRhiShader
15{
16public:
17 SmoothTextureMaterialRhiShader();
18
19 bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
20};
21
22
23QSGSmoothTextureMaterial::QSGSmoothTextureMaterial()
24{
25 setFlag(flags: RequiresFullMatrixExceptTranslate, on: true);
26 setFlag(flags: Blending, on: true);
27}
28
29void QSGSmoothTextureMaterial::setTexture(QSGTexture *texture)
30{
31 m_texture = texture;
32}
33
34QSGMaterialType *QSGSmoothTextureMaterial::type() const
35{
36 static QSGMaterialType type;
37 return &type;
38}
39
40QSGMaterialShader *QSGSmoothTextureMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
41{
42 Q_UNUSED(renderMode);
43 return new SmoothTextureMaterialRhiShader;
44}
45
46SmoothTextureMaterialRhiShader::SmoothTextureMaterialRhiShader()
47{
48 setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothtexture.vert.qsb"));
49 setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/smoothtexture.frag.qsb"));
50}
51
52bool SmoothTextureMaterialRhiShader::updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
53{
54 bool changed = false;
55 QByteArray *buf = state.uniformData();
56
57 if (!oldMaterial) {
58 // The viewport is constant, so set the pixel size uniform only once (per batches with the same material).
59 const QRect r = state.viewportRect();
60 const QVector2D v(2.0f / r.width(), 2.0f / r.height());
61 memcpy(dest: buf->data() + 64 + 8, src: &v, n: 8);
62 changed = true;
63 }
64
65 changed |= QSGTextureMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial);
66
67 return changed;
68}
69
70
71QSGDefaultInternalImageNode::QSGDefaultInternalImageNode(QSGDefaultRenderContext *rc)
72 : m_rc(rc)
73{
74 setMaterial(&m_materialO);
75 setOpaqueMaterial(&m_material);
76}
77
78void QSGDefaultInternalImageNode::setFiltering(QSGTexture::Filtering filtering)
79{
80 if (m_material.filtering() == filtering)
81 return;
82
83 m_material.setFiltering(filtering);
84 m_materialO.setFiltering(filtering);
85 m_smoothMaterial.setFiltering(filtering);
86 markDirty(bits: DirtyMaterial);
87}
88
89void QSGDefaultInternalImageNode::setMipmapFiltering(QSGTexture::Filtering filtering)
90{
91 if (m_material.mipmapFiltering() == filtering)
92 return;
93
94 m_material.setMipmapFiltering(filtering);
95 m_materialO.setMipmapFiltering(filtering);
96 m_smoothMaterial.setMipmapFiltering(filtering);
97 markDirty(bits: DirtyMaterial);
98}
99
100void QSGDefaultInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode)
101{
102 if (m_material.verticalWrapMode() == wrapMode)
103 return;
104
105 m_material.setVerticalWrapMode(wrapMode);
106 m_materialO.setVerticalWrapMode(wrapMode);
107 m_smoothMaterial.setVerticalWrapMode(wrapMode);
108 markDirty(bits: DirtyMaterial);
109}
110
111void QSGDefaultInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode)
112{
113 if (m_material.horizontalWrapMode() == wrapMode)
114 return;
115
116 m_material.setHorizontalWrapMode(wrapMode);
117 m_materialO.setHorizontalWrapMode(wrapMode);
118 m_smoothMaterial.setHorizontalWrapMode(wrapMode);
119 markDirty(bits: DirtyMaterial);
120}
121
122void QSGDefaultInternalImageNode::updateMaterialAntialiasing()
123{
124 if (m_antialiasing) {
125 setMaterial(&m_smoothMaterial);
126 setOpaqueMaterial(nullptr);
127 } else {
128 setMaterial(&m_materialO);
129 setOpaqueMaterial(&m_material);
130 }
131}
132
133void QSGDefaultInternalImageNode::setMaterialTexture(QSGTexture *texture)
134{
135 m_material.setTexture(texture);
136 m_materialO.setTexture(texture);
137 m_smoothMaterial.setTexture(texture);
138}
139
140QSGTexture *QSGDefaultInternalImageNode::materialTexture() const
141{
142 return m_material.texture();
143}
144
145bool QSGDefaultInternalImageNode::updateMaterialBlending()
146{
147 const bool alpha = m_material.flags() & QSGMaterial::Blending;
148 if (materialTexture() && alpha != materialTexture()->hasAlphaChannel()) {
149 m_material.setFlag(flags: QSGMaterial::Blending, on: !alpha);
150 return true;
151 }
152 return false;
153}
154
155inline static bool isPowerOfTwo(int x)
156{
157 // Assumption: x >= 1
158 return x == (x & -x);
159}
160
161bool QSGDefaultInternalImageNode::supportsWrap(const QSize &size) const
162{
163 bool npotSupported = m_rc->rhi() && m_rc->rhi()->isFeatureSupported(feature: QRhi::NPOTTextureRepeat);
164 return npotSupported || (isPowerOfTwo(x: size.width()) && isPowerOfTwo(x: size.height()));
165}
166
167QT_END_NAMESPACE
168

source code of qtdeclarative/src/quick/scenegraph/qsgdefaultinternalimagenode.cpp