1 /****************************************************************************
2 **
3 ** Copyright (C) 2008-2012 NVIDIA Corporation.
4 ** Copyright (C) 2019 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of Qt Quick 3D.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #include <QtQuick3DRender/private/qssgrendercontext_p.h>
32 #include <QtQuick3DRender/private/qssgrendertexturebase_p.h>
33 
34 #include <limits>
35 
36 QT_BEGIN_NAMESPACE
37 
38 class QSSGRenderTextureSampler
39 {
40 public:
41     QSSGRenderTextureMinifyingOp minFilter = QSSGRenderTextureMinifyingOp::Linear;
42     QSSGRenderTextureMagnifyingOp magFilter = QSSGRenderTextureMagnifyingOp::Linear;
43     QSSGRenderTextureCoordOp wrapS = QSSGRenderTextureCoordOp::ClampToEdge;
44     QSSGRenderTextureCoordOp wrapT = QSSGRenderTextureCoordOp::ClampToEdge;
45     QSSGRenderTextureCoordOp wrapR = QSSGRenderTextureCoordOp::ClampToEdge;
46     QSSGRenderTextureSwizzleMode swizzleMode = QSSGRenderTextureSwizzleMode::NoSwizzle;
47     float minLod = -1000.;
48     float maxLod = 1000.;
49     float lodBias = 0.;
50     QSSGRenderTextureCompareMode compareMode = QSSGRenderTextureCompareMode::NoCompare;
51     QSSGRenderTextureCompareOp compareOp = QSSGRenderTextureCompareOp::LessThanOrEqual;
52     float m_anisotropy = 1.;
53 
54     /**
55      * @brief constructor
56      *
57      * @param[in] context		Pointer to context
58      * @param[in] fnd			Pointer to foundation
59      * @param[in] minFilter		Texture min filter
60      * @param[in] magFilter		Texture mag filter
61      * @param[in] wrapS			Texture coord generation for S
62      * @param[in] wrapT			Texture coord generation for T
63      * @param[in] wrapR			Texture coord generation for R
64      * @param[in] swizzleMode	Texture swizzle mode
65      * @param[in] minLod		Texture min level of detail
66      * @param[in] maxLod		Texture max level of detail
67      * @param[in] lodBias		Texture level of detail bias (unused)
68      * @param[in] compareMode	Texture compare mode
69      * @param[in] compareFunc	Texture compare function
70      * @param[in] anisoFilter	Aniso filter value [1.0, 16.0]
71      * @param[in] borderColor	Texture border color float[4] (unused)
72      *
73      * @return No return.
74      */
QSSGRenderTextureSampler(const QSSGRef<QSSGRenderContext> & context)75     explicit QSSGRenderTextureSampler(const QSSGRef<QSSGRenderContext> &context)
76         : m_backend(context->backend())
77         , m_handle(nullptr)
78     {
79         // create backend handle
80         m_handle = m_backend->createSampler();
81     }
82 
~QSSGRenderTextureSampler()83     ~QSSGRenderTextureSampler()
84     {
85         if (m_handle)
86             m_backend->releaseSampler(m_handle);
87     }
88 
89     /**
90      * @brief get the backend object handle
91      *
92      * @return the backend object handle.
93      */
handle() const94     QSSGRenderBackend::QSSGRenderBackendSamplerObject handle() const { return m_handle; }
95 
96 private:
97     QSSGRef<QSSGRenderBackend> m_backend; ///< pointer to backend
98     QSSGRenderBackend::QSSGRenderBackendSamplerObject m_handle = nullptr;
99 };
100 
101 
QSSGRenderTextureBase(const QSSGRef<QSSGRenderContext> & context,QSSGRenderTextureTargetType texTarget,bool ownsTexture)102 QSSGRenderTextureBase::QSSGRenderTextureBase(const QSSGRef<QSSGRenderContext> &context,
103                                                  QSSGRenderTextureTargetType texTarget,
104                                                  bool ownsTexture)
105     : m_context(context)
106     , m_backend(context->backend())
107     , m_handle(nullptr)
108     , m_textureUnit(std::numeric_limits<qint32>::max())
109     , m_samplerParamsDirty(true)
110     , m_texStateDirty(false)
111     , m_sampleCount(1)
112     , m_format(QSSGRenderTextureFormat::Unknown)
113     , m_texTarget(texTarget)
114     , m_baseLevel(0)
115     , m_maxLevel(1000)
116     , m_maxMipLevel(0)
117     , m_immutable(false)
118     , m_ownsTexture(ownsTexture)
119 {
120     if (m_ownsTexture)
121         m_handle = m_backend->createTexture();
122     m_sampler = new QSSGRenderTextureSampler(context);
123 }
124 
~QSSGRenderTextureBase()125 QSSGRenderTextureBase::~QSSGRenderTextureBase()
126 {
127     if (m_sampler)
128         delete m_sampler;
129     if (m_handle && m_ownsTexture)
130         m_backend->releaseTexture(m_handle);
131 }
132 
setBaseLevel(qint32 value)133 void QSSGRenderTextureBase::setBaseLevel(qint32 value)
134 {
135     if (m_baseLevel != value) {
136         m_baseLevel = value;
137         m_texStateDirty = true;
138     }
139 }
140 
setMaxLevel(qint32 value)141 void QSSGRenderTextureBase::setMaxLevel(qint32 value)
142 {
143     if (m_maxLevel != value) {
144         m_maxLevel = value;
145         m_texStateDirty = true;
146     }
147 }
148 
setMinFilter(QSSGRenderTextureMinifyingOp value)149 void QSSGRenderTextureBase::setMinFilter(QSSGRenderTextureMinifyingOp value)
150 {
151     if (m_sampler->minFilter != value) {
152         m_sampler->minFilter = value;
153         m_samplerParamsDirty = true;
154     }
155 }
156 
setMagFilter(QSSGRenderTextureMagnifyingOp value)157 void QSSGRenderTextureBase::setMagFilter(QSSGRenderTextureMagnifyingOp value)
158 {
159     if (m_sampler->magFilter != value) {
160         m_sampler->magFilter = value;
161         m_samplerParamsDirty = true;
162     }
163 }
164 
setTextureWrapS(QSSGRenderTextureCoordOp value)165 void QSSGRenderTextureBase::setTextureWrapS(QSSGRenderTextureCoordOp value)
166 {
167     if (m_sampler->wrapS != value) {
168         m_sampler->wrapS = value;
169         m_samplerParamsDirty = true;
170     }
171 }
172 
setTextureWrapT(QSSGRenderTextureCoordOp value)173 void QSSGRenderTextureBase::setTextureWrapT(QSSGRenderTextureCoordOp value)
174 {
175     if (m_sampler->wrapT != value) {
176         m_sampler->wrapT = value;
177         m_samplerParamsDirty = true;
178     }
179 }
180 
setTextureCompareMode(QSSGRenderTextureCompareMode value)181 void QSSGRenderTextureBase::setTextureCompareMode(QSSGRenderTextureCompareMode value)
182 {
183     if (m_sampler->compareMode != value) {
184         m_sampler->compareMode = value;
185         m_samplerParamsDirty = true;
186     }
187 }
188 
setTextureCompareFunc(QSSGRenderTextureCompareOp value)189 void QSSGRenderTextureBase::setTextureCompareFunc(QSSGRenderTextureCompareOp value)
190 {
191     if (m_sampler->compareOp != value) {
192         m_sampler->compareOp = value;
193         m_samplerParamsDirty = true;
194     }
195 }
196 
applyTexParams()197 void QSSGRenderTextureBase::applyTexParams()
198 {
199     if (m_samplerParamsDirty) {
200         m_backend->updateSampler(m_sampler->handle(),
201                                  m_texTarget,
202                                  m_sampler->minFilter,
203                                  m_sampler->magFilter,
204                                  m_sampler->wrapS,
205                                  m_sampler->wrapT,
206                                  m_sampler->wrapR,
207                                  m_sampler->minLod,
208                                  m_sampler->maxLod,
209                                  m_sampler->lodBias,
210                                  m_sampler->compareMode,
211                                  m_sampler->compareOp);
212 
213         m_samplerParamsDirty = false;
214     }
215 
216     if (m_texStateDirty) {
217         m_backend->updateTextureObject(m_handle, m_texTarget, m_baseLevel, m_maxLevel);
218         m_texStateDirty = false;
219     }
220 }
221 
applyTexSwizzle()222 void QSSGRenderTextureBase::applyTexSwizzle()
223 {
224     QSSGRenderTextureSwizzleMode theSwizzleMode = m_backend->getTextureSwizzleMode(m_format);
225     if (theSwizzleMode != m_sampler->swizzleMode) {
226         m_sampler->swizzleMode = theSwizzleMode;
227         m_backend->updateTextureSwizzle(m_handle, m_texTarget, theSwizzleMode);
228     }
229 }
230 QT_END_NAMESPACE
231