1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQuick module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include <private/qquickshadereffect_p.h>
41#include <private/qsgcontextplugin_p.h>
42#include <private/qquickitem_p.h>
43#if QT_CONFIG(opengl)
44#include <private/qquickopenglshadereffect_p.h>
45#endif
46#include <private/qquickgenericshadereffect_p.h>
47#if QT_CONFIG(opengl) /* || QT_CONFIG(vulkan) || defined(Q_OS_WIN) || defined(Q_OS_DARWIN) */
48#include <private/qsgrhisupport_p.h>
49#endif
50
51QT_BEGIN_NAMESPACE
52
53/*!
54 \qmltype ShaderEffect
55 \instantiates QQuickShaderEffect
56 \inqmlmodule QtQuick
57 \inherits Item
58 \ingroup qtquick-effects
59 \brief Applies custom shaders to a rectangle.
60
61 The ShaderEffect type applies a custom
62 \l{vertexShader}{vertex} and \l{fragmentShader}{fragment (pixel)} shader to a
63 rectangle. It allows you to write effects such as drop shadow, blur,
64 colorize and page curl directly in QML.
65
66 \note Depending on the Qt Quick scenegraph backend in use, the ShaderEffect
67 type may not be supported (for example, with the software backend), or may
68 use a different shading language with rules and expectations different from
69 OpenGL and GLSL.
70
71 \section1 OpenGL and GLSL
72
73 There are two types of input to the \l vertexShader:
74 uniform variables and attributes. Some are predefined:
75 \list
76 \li uniform mat4 qt_Matrix - combined transformation
77 matrix, the product of the matrices from the root item to this
78 ShaderEffect, and an orthogonal projection.
79 \li uniform float qt_Opacity - combined opacity, the product of the
80 opacities from the root item to this ShaderEffect.
81 \li attribute vec4 qt_Vertex - vertex position, the top-left vertex has
82 position (0, 0), the bottom-right (\l{Item::width}{width},
83 \l{Item::height}{height}).
84 \li attribute vec2 qt_MultiTexCoord0 - texture coordinate, the top-left
85 coordinate is (0, 0), the bottom-right (1, 1). If \l supportsAtlasTextures
86 is true, coordinates will be based on position in the atlas instead.
87 \endlist
88
89 In addition, any property that can be mapped to an OpenGL Shading Language
90 (GLSL) type is available as a uniform variable. The following list shows
91 how properties are mapped to GLSL uniform variables:
92 \list
93 \li bool, int, qreal -> bool, int, float - If the type in the shader is not
94 the same as in QML, the value is converted automatically.
95 \li QColor -> vec4 - When colors are passed to the shader, they are first
96 premultiplied. Thus Qt.rgba(0.2, 0.6, 1.0, 0.5) becomes
97 vec4(0.1, 0.3, 0.5, 0.5) in the shader, for example.
98 \li QRect, QRectF -> vec4 - Qt.rect(x, y, w, h) becomes vec4(x, y, w, h) in
99 the shader.
100 \li QPoint, QPointF, QSize, QSizeF -> vec2
101 \li QVector3D -> vec3
102 \li QVector4D -> vec4
103 \li QTransform -> mat3
104 \li QMatrix4x4 -> mat4
105 \li QQuaternion -> vec4, scalar value is \c w.
106 \li \l Image -> sampler2D - Origin is in the top-left corner, and the
107 color values are premultiplied. The texture is provided as is,
108 excluding the Image item's fillMode. To include fillMode, use a
109 ShaderEffectSource or Image::layer::enabled.
110 \li \l ShaderEffectSource -> sampler2D - Origin is in the top-left
111 corner, and the color values are premultiplied.
112 \endlist
113
114 The QML scene graph back-end may choose to allocate textures in texture
115 atlases. If a texture allocated in an atlas is passed to a ShaderEffect,
116 it is by default copied from the texture atlas into a stand-alone texture
117 so that the texture coordinates span from 0 to 1, and you get the expected
118 wrap modes. However, this will increase the memory usage. To avoid the
119 texture copy, set \l supportsAtlasTextures for simple shaders using
120 qt_MultiTexCoord0, or for each "uniform sampler2D <name>" declare a
121 "uniform vec4 qt_SubRect_<name>" which will be assigned the texture's
122 normalized source rectangle. For stand-alone textures, the source rectangle
123 is [0, 1]x[0, 1]. For textures in an atlas, the source rectangle corresponds
124 to the part of the texture atlas where the texture is stored.
125 The correct way to calculate the texture coordinate for a texture called
126 "source" within a texture atlas is
127 "qt_SubRect_source.xy + qt_SubRect_source.zw * qt_MultiTexCoord0".
128
129 The output from the \l fragmentShader should be premultiplied. If
130 \l blending is enabled, source-over blending is used. However, additive
131 blending can be achieved by outputting zero in the alpha channel.
132
133 \table 70%
134 \row
135 \li \image declarative-shadereffectitem.png
136 \li \qml
137 import QtQuick 2.0
138
139 Rectangle {
140 width: 200; height: 100
141 Row {
142 Image { id: img;
143 sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
144 ShaderEffect {
145 width: 100; height: 100
146 property variant src: img
147 vertexShader: "
148 uniform highp mat4 qt_Matrix;
149 attribute highp vec4 qt_Vertex;
150 attribute highp vec2 qt_MultiTexCoord0;
151 varying highp vec2 coord;
152 void main() {
153 coord = qt_MultiTexCoord0;
154 gl_Position = qt_Matrix * qt_Vertex;
155 }"
156 fragmentShader: "
157 varying highp vec2 coord;
158 uniform sampler2D src;
159 uniform lowp float qt_Opacity;
160 void main() {
161 lowp vec4 tex = texture2D(src, coord);
162 gl_FragColor = vec4(vec3(dot(tex.rgb,
163 vec3(0.344, 0.5, 0.156))),
164 tex.a) * qt_Opacity;
165 }"
166 }
167 }
168 }
169 \endqml
170 \endtable
171
172 \note Scene Graph textures have origin in the top-left corner rather than
173 bottom-left which is common in OpenGL.
174
175 For information about the GLSL version being used, see \l QtQuick::GraphicsInfo.
176
177 Starting from Qt 5.8 ShaderEffect also supports reading the GLSL source
178 code from files. Whenever the fragmentShader or vertexShader property value
179 is a URL with the \c file or \c qrc schema, it is treated as a file
180 reference and the source code is read from the specified file.
181
182 \section1 Direct3D and HLSL
183
184 Direct3D backends provide ShaderEffect support with HLSL. The Direct3D 12
185 backend requires using at least Shader Model 5.0 both for vertex and pixel
186 shaders. When necessary, GraphicsInfo.shaderType can be used to decide
187 at runtime what kind of value to assign to \l fragmentShader or
188 \l vertexShader.
189
190 All concepts described above for OpenGL and GLSL apply to Direct3D and HLSL
191 as well. There are however a number of notable practical differences, which
192 are the following:
193
194 Instead of uniforms, HLSL shaders are expected to use a single constant
195 buffer, assigned to register \c b0. The special names \c qt_Matrix,
196 \c qt_Opacity, and \c qt_SubRect_<name> function the same way as with GLSL.
197 All other members of the buffer are expected to map to properties in the
198 ShaderEffect item.
199
200 \note The buffer layout must be compatible for both shaders. This means
201 that application-provided shaders must make sure \c qt_Matrix and
202 \c qt_Opacity are included in the buffer, starting at offset 0, when custom
203 code is provided for one type of shader only, leading to ShaderEffect
204 providing the other shader. This is due to ShaderEffect's built-in shader code
205 declaring a constant buffer containing \c{float4x4 qt_Matrix; float qt_Opacity;}.
206
207 Unlike GLSL's attributes, no names are used for vertex input elements.
208 Therefore qt_Vertex and qt_MultiTexCoord0 are not relevant. Instead, the
209 standard Direct3D semantics, \c POSITION and \c TEXCOORD (or \c TEXCOORD0)
210 are used for identifying the correct input layout.
211
212 Unlike GLSL's samplers, texture and sampler objects are separate in HLSL.
213 Shaders are expected to expect 2D, non-array, non-multisample textures.
214 Both the texture and sampler binding points are expected to be sequential
215 and start from 0 (meaning registers \c{t0, t1, ...}, and \c{s0, s1, ...},
216 respectively). Unlike with OpenGL, samplers are not mapped to Qt Quick item
217 properties and therefore the name of the sampler is not relevant. Instead,
218 it is the textures that map to properties referencing \l Image or
219 \l ShaderEffectSource items.
220
221 Unlike OpenGL, backends for modern APIs will typically prefer offline
222 compilation and shipping pre-compiled bytecode with applications instead of
223 inlined shader source strings. In this case the string properties for
224 vertex and fragment shaders are treated as URLs referring to local files or
225 files shipped via the Qt resource system.
226
227 To check at runtime what is supported, use the
228 GraphicsInfo.shaderSourceType and GraphicsInfo.shaderCompilationType
229 properties. Note that these are bitmasks, because some backends may support
230 multiple approaches.
231
232 In case of Direct3D 12, all combinations are supported. If the vertexShader
233 and fragmentShader properties form a valid URL with the \c file or \c qrc
234 schema, the bytecode or HLSL source code is read from the specified file.
235 The type of the file contents is detected automatically. Otherwise, the
236 string is treated as HLSL source code and is compiled at runtime, assuming
237 Shader Model 5.0 and an entry point of \c{"main"}. This allows dynamically
238 constructing shader strings. However, whenever the shader source code is
239 static, it is strongly recommended to pre-compile to bytecode using the
240 \c fxc tool and refer to these files from QML. This will be a lot more
241 efficient at runtime and allows catching syntax errors in the shaders at
242 compile time.
243
244 Unlike OpenGL, the Direct3D backend is able to perform runtime shader
245 compilation on dedicated threads. This is managed transparently to the
246 applications, and means that ShaderEffect items that contain HLSL source
247 strings do not block the rendering or other parts of the application until
248 the bytecode is ready.
249
250 Using files with bytecode is more flexible also when it comes to the entry
251 point name (it can be anything, not limited to \c main) and the shader
252 model (it can be something newer than 5.0, for instance 5.1).
253
254 \table 70%
255 \row
256 \li \qml
257 import QtQuick 2.0
258
259 Rectangle {
260 width: 200; height: 100
261 Row {
262 Image { id: img;
263 sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
264 ShaderEffect {
265 width: 100; height: 100
266 property variant src: img
267 fragmentShader: "qrc:/effect_ps.cso"
268 }
269 }
270 }
271 \endqml
272 \row
273 \li where \c effect_ps.cso is the compiled bytecode for the following HLSL shader:
274 \code
275 cbuffer ConstantBuffer : register(b0)
276 {
277 float4x4 qt_Matrix;
278 float qt_Opacity;
279 };
280 Texture2D src : register(t0);
281 SamplerState srcSampler : register(s0);
282 float4 ExamplePixelShader(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET
283 {
284 float4 tex = src.Sample(srcSampler, coord);
285 float3 col = dot(tex.rgb, float3(0.344, 0.5, 0.156));
286 return float4(col, tex.a) * qt_Opacity;
287 }
288 \endcode
289 \endtable
290
291 The above is equivalent to the OpenGL example presented earlier. The vertex
292 shader is provided implicitly by ShaderEffect. Note that the output of the
293 pixel shader is using premultiplied alpha and that \c qt_Matrix is present
294 in the constant buffer at offset 0, even though the pixel shader does not
295 use the value.
296
297 If desired, the HLSL source code can be placed directly into the QML
298 source, similarly to how its done with GLSL. The only difference in this
299 case is the entry point name, which must be \c main when using inline
300 source strings.
301
302 Alternatively, we could also have referred to a file containing the source
303 of the effect instead of the compiled bytecode version.
304
305 Some effects will want to provide a vertex shader as well. Below is a
306 similar effect with both the vertex and fragment shader provided by the
307 application. This time the colorization factor is provided by the QML item
308 instead of hardcoding it in the shader. This can allow, among others,
309 animating the value using QML's and Qt Quick's standard facilities.
310
311 \table 70%
312 \row
313 \li \qml
314 import QtQuick 2.0
315
316 Rectangle {
317 width: 200; height: 100
318 Row {
319 Image { id: img;
320 sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
321 ShaderEffect {
322 width: 100; height: 100
323 property variant src: img
324 property variant color: Qt.vector3d(0.344, 0.5, 0.156)
325 vertexShader: "qrc:/effect_vs.cso"
326 fragmentShader: "qrc:/effect_ps.cso"
327 }
328 }
329 }
330 \endqml
331 \row
332 \li where \c effect_vs.cso and \c effect_ps.cso are the compiled bytecode
333 for \c ExampleVertexShader and \c ExamplePixelShader. The source code is
334 presented as one snippet here, the shaders can however be placed in
335 separate source files as well.
336 \code
337 cbuffer ConstantBuffer : register(b0)
338 {
339 float4x4 qt_Matrix;
340 float qt_Opacity;
341 float3 color;
342 };
343 Texture2D src : register(t0);
344 SamplerState srcSampler : register(s0);
345 struct PSInput
346 {
347 float4 position : SV_POSITION;
348 float2 coord : TEXCOORD0;
349 };
350 PSInput ExampleVertexShader(float4 position : POSITION, float2 coord : TEXCOORD0)
351 {
352 PSInput result;
353 result.position = mul(qt_Matrix, position);
354 result.coord = coord;
355 return result;
356 }
357 float4 ExamplePixelShader(PSInput input) : SV_TARGET
358 {
359 float4 tex = src.Sample(srcSampler, coord);
360 float3 col = dot(tex.rgb, color);
361 return float4(col, tex.a) * qt_Opacity;
362 }
363 \endcode
364 \endtable
365
366 \note With OpenGL the \c y coordinate runs from bottom to top whereas with
367 Direct 3D it goes top to bottom. For shader effect sources Qt Quick hides
368 the difference by treating QtQuick::ShaderEffectSource::textureMirroring as
369 appropriate, meaning texture coordinates in HLSL version of the shaders
370 will not need any adjustments compared to the equivalent GLSL code.
371
372 \section1 Cross-platform, Cross-API ShaderEffect Items
373
374 Some applications will want to be functional with multiple accelerated
375 graphics backends. This has consequences for ShaderEffect items because the
376 supported shading languages may vary from backend to backend.
377
378 There are two approaches to handle this: either write conditional property
379 values based on GraphicsInfo.shaderType, or use file selectors. In practice
380 the latter is strongly recommended as it leads to more concise and cleaner
381 application code. The only case it is not suitable is when the source
382 strings are constructed dynamically.
383
384 \table 70%
385 \row
386 \li \qml
387 import QtQuick 2.8 // for GraphicsInfo
388
389 Rectangle {
390 width: 200; height: 100
391 Row {
392 Image { id: img;
393 sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
394 ShaderEffect {
395 width: 100; height: 100
396 property variant src: img
397 property variant color: Qt.vector3d(0.344, 0.5, 0.156)
398 fragmentShader: GraphicsInfo.shaderType === GraphicsInfo.GLSL ?
399 "varying highp vec2 coord;
400 uniform sampler2D src;
401 uniform lowp float qt_Opacity;
402 void main() {
403 lowp vec4 tex = texture2D(src, coord);
404 gl_FragColor = vec4(vec3(dot(tex.rgb,
405 vec3(0.344, 0.5, 0.156))),
406 tex.a) * qt_Opacity;"
407 : GraphicsInfo.shaderType === GraphicsInfo.HLSL ?
408 "cbuffer ConstantBuffer : register(b0)
409 {
410 float4x4 qt_Matrix;
411 float qt_Opacity;
412 };
413 Texture2D src : register(t0);
414 SamplerState srcSampler : register(s0);
415 float4 ExamplePixelShader(float4 position : SV_POSITION, float2 coord : TEXCOORD0) : SV_TARGET
416 {
417 float4 tex = src.Sample(srcSampler, coord);
418 float3 col = dot(tex.rgb, float3(0.344, 0.5, 0.156));
419 return float4(col, tex.a) * qt_Opacity;
420 }"
421 : ""
422 }
423 }
424 }
425 \endqml
426 \row
427
428 \li This is the first approach based on GraphicsInfo. Note that the value
429 reported by GraphicsInfo is not up-to-date until the ShaderEffect item gets
430 associated with a QQuickWindow. Before that, the reported value is
431 GraphicsInfo.UnknownShadingLanguage. The alternative is to place the GLSL
432 source code and the compiled D3D bytecode into the files
433 \c{shaders/effect.frag} and \c{shaders/+hlsl/effect.frag}, include them in
434 the Qt resource system, and let the ShaderEffect's internal QFileSelector
435 do its job. The selector-less version is the GLSL source, while the \c hlsl
436 selector is used when running on the D3D12 backend. The file under
437 \c{+hlsl} can then contain either HLSL source code or compiled bytecode
438 from the \c fxc tool. Additionally, when using a version 3.2 or newer core
439 profile context with OpenGL, GLSL sources with a core profile compatible
440 syntax can be placed under \c{+glslcore}.
441 \qml
442 import QtQuick 2.8 // for GraphicsInfo
443
444 Rectangle {
445 width: 200; height: 100
446 Row {
447 Image { id: img;
448 sourceSize { width: 100; height: 100 } source: "qt-logo.png" }
449 ShaderEffect {
450 width: 100; height: 100
451 property variant src: img
452 property variant color: Qt.vector3d(0.344, 0.5, 0.156)
453 fragmentShader: "qrc:shaders/effect.frag" // selects the correct variant automatically
454 }
455 }
456 }
457 \endqml
458 \endtable
459
460 \section1 ShaderEffect and Item Layers
461
462 The ShaderEffect type can be combined with \l {Item Layers} {layered items}.
463
464 \table
465 \row
466 \li \b {Layer with effect disabled} \inlineimage qml-shadereffect-nolayereffect.png
467 \li \b {Layer with effect enabled} \inlineimage qml-shadereffect-layereffect.png
468 \row
469 \li \snippet qml/layerwitheffect.qml 1
470 \endtable
471
472 It is also possible to combine multiple layered items:
473
474 \table
475 \row
476 \li \inlineimage qml-shadereffect-opacitymask.png
477 \row
478 \li \snippet qml/opacitymask.qml 1
479 \endtable
480
481 \section1 Other Notes
482
483 By default, the ShaderEffect consists of four vertices, one for each
484 corner. For non-linear vertex transformations, like page curl, you can
485 specify a fine grid of vertices by specifying a \l mesh resolution.
486
487 The \l {Qt Graphical Effects} module contains several ready-made effects
488 for using with Qt Quick applications.
489
490 \sa {Item Layers}
491*/
492
493class QQuickShaderEffectPrivate : public QQuickItemPrivate
494{
495 Q_DECLARE_PUBLIC(QQuickShaderEffect)
496
497public:
498 void updatePolish() override;
499};
500
501QSGContextFactoryInterface::Flags qsg_backend_flags();
502
503QQuickShaderEffect::QQuickShaderEffect(QQuickItem *parent)
504 : QQuickItem(*new QQuickShaderEffectPrivate, parent),
505#if QT_CONFIG(opengl)
506 m_glImpl(nullptr),
507#endif
508 m_impl(nullptr)
509{
510 setFlag(QQuickItem::ItemHasContents);
511
512#if QT_CONFIG(opengl) /* || QT_CONFIG(vulkan) || defined(Q_OS_WIN) || defined(Q_OS_DARWIN) */
513 if (QSGRhiSupport::instance()->isRhiEnabled()) {
514 m_impl = new QQuickGenericShaderEffect(this, this);
515 } else
516#endif
517 {
518#if QT_CONFIG(opengl)
519 if (!qsg_backend_flags().testFlag(QSGContextFactoryInterface::SupportsShaderEffectNode))
520 m_glImpl = new QQuickOpenGLShaderEffect(this, this);
521
522 if (!m_glImpl)
523#endif
524 m_impl = new QQuickGenericShaderEffect(this, this);
525 }
526}
527
528QQuickShaderEffect::~QQuickShaderEffect()
529{
530 // Delete the implementations now, while they still have have
531 // valid references back to us.
532#if QT_CONFIG(opengl)
533 auto *glImpl = m_glImpl;
534 m_glImpl = nullptr;
535 delete glImpl;
536#endif
537 auto *impl = m_impl;
538 m_impl = nullptr;
539 delete impl;
540}
541
542/*!
543 \qmlproperty string QtQuick::ShaderEffect::fragmentShader
544
545 This property holds the fragment (pixel) shader's source code or a
546 reference to the pre-compiled bytecode. Some APIs, like OpenGL, always
547 support runtime compilation and therefore the traditional Qt Quick way of
548 inlining shader source strings is functional. Qt Quick backends for other
549 APIs may however limit support to pre-compiled bytecode like SPIR-V or D3D
550 shader bytecode. There the string is simply a filename, which may be a file
551 in the filesystem or bundled with the executable via Qt's resource system.
552
553 With GLSL the default shader expects the texture coordinate to be passed
554 from the vertex shader as \c{varying highp vec2 qt_TexCoord0}, and it
555 samples from a sampler2D named \c source. With HLSL the texture is named
556 \c source, while the vertex shader is expected to provide
557 \c{float2 coord : TEXCOORD0} in its output in addition to
558 \c{float4 position : SV_POSITION} (names can differ since linking is done
559 based on the semantics).
560
561 \sa vertexShader, GraphicsInfo
562*/
563
564QByteArray QQuickShaderEffect::fragmentShader() const
565{
566#if QT_CONFIG(opengl)
567 if (m_glImpl)
568 return m_glImpl->fragmentShader();
569#endif
570 return m_impl->fragmentShader();
571}
572
573void QQuickShaderEffect::setFragmentShader(const QByteArray &code)
574{
575#if QT_CONFIG(opengl)
576 if (m_glImpl) {
577 m_glImpl->setFragmentShader(code);
578 return;
579 }
580#endif
581 m_impl->setFragmentShader(code);
582}
583
584/*!
585 \qmlproperty string QtQuick::ShaderEffect::vertexShader
586
587 This property holds the vertex shader's source code or a reference to the
588 pre-compiled bytecode. Some APIs, like OpenGL, always support runtime
589 compilation and therefore the traditional Qt Quick way of inlining shader
590 source strings is functional. Qt Quick backends for other APIs may however
591 limit support to pre-compiled bytecode like SPIR-V or D3D shader bytecode.
592 There the string is simply a filename, which may be a file in the
593 filesystem or bundled with the executable via Qt's resource system.
594
595 With GLSL the default shader passes the texture coordinate along to the
596 fragment shader as \c{varying highp vec2 qt_TexCoord0}. With HLSL it is
597 enough to use the standard \c TEXCOORD0 semantic, for example
598 \c{float2 coord : TEXCOORD0}.
599
600 \sa fragmentShader, GraphicsInfo
601*/
602
603QByteArray QQuickShaderEffect::vertexShader() const
604{
605#if QT_CONFIG(opengl)
606 if (m_glImpl)
607 return m_glImpl->vertexShader();
608#endif
609 return m_impl->vertexShader();
610}
611
612void QQuickShaderEffect::setVertexShader(const QByteArray &code)
613{
614#if QT_CONFIG(opengl)
615 if (m_glImpl) {
616 m_glImpl->setVertexShader(code);
617 return;
618 }
619#endif
620 m_impl->setVertexShader(code);
621}
622
623/*!
624 \qmlproperty bool QtQuick::ShaderEffect::blending
625
626 If this property is true, the output from the \l fragmentShader is blended
627 with the background using source-over blend mode. If false, the background
628 is disregarded. Blending decreases the performance, so you should set this
629 property to false when blending is not needed. The default value is true.
630*/
631
632bool QQuickShaderEffect::blending() const
633{
634#if QT_CONFIG(opengl)
635 if (m_glImpl)
636 return m_glImpl->blending();
637#endif
638 return m_impl->blending();
639}
640
641void QQuickShaderEffect::setBlending(bool enable)
642{
643#if QT_CONFIG(opengl)
644 if (m_glImpl) {
645 m_glImpl->setBlending(enable);
646 return;
647 }
648#endif
649 m_impl->setBlending(enable);
650}
651
652/*!
653 \qmlproperty variant QtQuick::ShaderEffect::mesh
654
655 This property defines the mesh used to draw the ShaderEffect. It can hold
656 any \l GridMesh object.
657 If a size value is assigned to this property, the ShaderEffect implicitly
658 uses a \l GridMesh with the value as
659 \l{GridMesh::resolution}{mesh resolution}. By default, this property is
660 the size 1x1.
661
662 \sa GridMesh
663*/
664
665QVariant QQuickShaderEffect::mesh() const
666{
667#if QT_CONFIG(opengl)
668 if (m_glImpl)
669 return m_glImpl->mesh();
670#endif
671 return m_impl->mesh();
672}
673
674void QQuickShaderEffect::setMesh(const QVariant &mesh)
675{
676#if QT_CONFIG(opengl)
677 if (m_glImpl) {
678 m_glImpl->setMesh(mesh);
679 return;
680 }
681#endif
682 m_impl->setMesh(mesh);
683}
684
685/*!
686 \qmlproperty enumeration QtQuick::ShaderEffect::cullMode
687
688 This property defines which sides of the item should be visible.
689
690 \list
691 \li ShaderEffect.NoCulling - Both sides are visible
692 \li ShaderEffect.BackFaceCulling - only front side is visible
693 \li ShaderEffect.FrontFaceCulling - only back side is visible
694 \endlist
695
696 The default is NoCulling.
697*/
698
699QQuickShaderEffect::CullMode QQuickShaderEffect::cullMode() const
700{
701#if QT_CONFIG(opengl)
702 if (m_glImpl)
703 return m_glImpl->cullMode();
704#endif
705 return m_impl->cullMode();
706}
707
708void QQuickShaderEffect::setCullMode(CullMode face)
709{
710#if QT_CONFIG(opengl)
711 if (m_glImpl) {
712 m_glImpl->setCullMode(face);
713 return;
714 }
715#endif
716 return m_impl->setCullMode(face);
717}
718
719/*!
720 \qmlproperty bool QtQuick::ShaderEffect::supportsAtlasTextures
721
722 Set this property true to confirm that your shader code doesn't rely on
723 qt_MultiTexCoord0 ranging from (0,0) to (1,1) relative to the mesh.
724 In this case the range of qt_MultiTexCoord0 will rather be based on the position
725 of the texture within the atlas. This property currently has no effect if there
726 is less, or more, than one sampler uniform used as input to your shader.
727
728 This differs from providing qt_SubRect_<name> uniforms in that the latter allows
729 drawing one or more textures from the atlas in a single ShaderEffect item, while
730 supportsAtlasTextures allows multiple instances of a ShaderEffect component using
731 a different source image from the atlas to be batched in a single draw.
732 Both prevent a texture from being copied out of the atlas when referenced by a ShaderEffect.
733
734 The default value is false.
735
736 \since 5.4
737 \since QtQuick 2.4
738*/
739
740bool QQuickShaderEffect::supportsAtlasTextures() const
741{
742#if QT_CONFIG(opengl)
743 if (m_glImpl)
744 return m_glImpl->supportsAtlasTextures();
745#endif
746 return m_impl->supportsAtlasTextures();
747}
748
749void QQuickShaderEffect::setSupportsAtlasTextures(bool supports)
750{
751#if QT_CONFIG(opengl)
752 if (m_glImpl) {
753 m_glImpl->setSupportsAtlasTextures(supports);
754 return;
755 }
756#endif
757 m_impl->setSupportsAtlasTextures(supports);
758}
759
760/*!
761 \qmlproperty enumeration QtQuick::ShaderEffect::status
762
763 This property tells the current status of the OpenGL shader program.
764
765 \list
766 \li ShaderEffect.Compiled - the shader program was successfully compiled and linked.
767 \li ShaderEffect.Uncompiled - the shader program has not yet been compiled.
768 \li ShaderEffect.Error - the shader program failed to compile or link.
769 \endlist
770
771 When setting the fragment or vertex shader source code, the status will
772 become Uncompiled. The first time the ShaderEffect is rendered with new
773 shader source code, the shaders are compiled and linked, and the status is
774 updated to Compiled or Error.
775
776 When runtime compilation is not in use and the shader properties refer to
777 files with bytecode, the status is always Compiled. The contents of the
778 shader is not examined (apart from basic reflection to discover vertex
779 input elements and constant buffer data) until later in the rendering
780 pipeline so potential errors (like layout or root signature mismatches)
781 will only be detected at a later point.
782
783 \sa log
784*/
785
786/*!
787 \qmlproperty string QtQuick::ShaderEffect::log
788
789 This property holds a log of warnings and errors from the latest attempt at
790 compiling and linking the OpenGL shader program. It is updated at the same
791 time \l status is set to Compiled or Error.
792
793 \sa status
794*/
795
796QString QQuickShaderEffect::log() const
797{
798#if QT_CONFIG(opengl)
799 if (m_glImpl)
800 return m_glImpl->log();
801#endif
802 return m_impl->log();
803}
804
805QQuickShaderEffect::Status QQuickShaderEffect::status() const
806{
807#if QT_CONFIG(opengl)
808 if (m_glImpl)
809 return m_glImpl->status();
810#endif
811 return m_impl->status();
812}
813
814bool QQuickShaderEffect::event(QEvent *e)
815{
816#if QT_CONFIG(opengl)
817 if (m_glImpl) {
818 m_glImpl->handleEvent(e);
819 return QQuickItem::event(e);
820 }
821#endif
822 if (m_impl)
823 m_impl->handleEvent(e);
824 return QQuickItem::event(e);
825}
826
827void QQuickShaderEffect::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
828{
829#if QT_CONFIG(opengl)
830 if (m_glImpl) {
831 m_glImpl->handleGeometryChanged(newGeometry, oldGeometry);
832 QQuickItem::geometryChanged(newGeometry, oldGeometry);
833 return;
834 }
835#endif
836 m_impl->handleGeometryChanged(newGeometry, oldGeometry);
837 QQuickItem::geometryChanged(newGeometry, oldGeometry);
838}
839
840QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData)
841{
842#if QT_CONFIG(opengl)
843 if (m_glImpl)
844 return m_glImpl->handleUpdatePaintNode(oldNode, updatePaintNodeData);
845#endif
846 return m_impl->handleUpdatePaintNode(oldNode, updatePaintNodeData);
847}
848
849void QQuickShaderEffect::componentComplete()
850{
851#if QT_CONFIG(opengl)
852 if (m_glImpl) {
853 m_glImpl->maybeUpdateShaders();
854 QQuickItem::componentComplete();
855 return;
856 }
857#endif
858 m_impl->maybeUpdateShaders();
859 QQuickItem::componentComplete();
860}
861
862void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &value)
863{
864#if QT_CONFIG(opengl)
865 if (m_glImpl) {
866 m_glImpl->handleItemChange(change, value);
867 QQuickItem::itemChange(change, value);
868 return;
869 }
870#endif
871 // It's possible for itemChange to be called during destruction when deleting
872 // the QQuickShaderEffectImpl. We nullify m_impl before deleting it via another pointer
873 // to it, so we must check that it's not null before trying to use it here.
874 if (m_impl)
875 m_impl->handleItemChange(change, value);
876 QQuickItem::itemChange(change, value);
877}
878
879bool QQuickShaderEffect::isComponentComplete() const
880{
881 return QQuickItem::isComponentComplete();
882}
883
884QString QQuickShaderEffect::parseLog() // for OpenGL-based autotests
885{
886#if QT_CONFIG(opengl)
887 if (m_glImpl)
888 return m_glImpl->parseLog();
889#endif
890 return m_impl->parseLog();
891}
892
893void QQuickShaderEffectPrivate::updatePolish()
894{
895 Q_Q(QQuickShaderEffect);
896 if (!qmlEngine(q))
897 return;
898#if QT_CONFIG(opengl)
899 if (q->m_glImpl) {
900 q->m_glImpl->maybeUpdateShaders();
901 return;
902 }
903#endif
904 q->m_impl->maybeUpdateShaders();
905}
906
907#if QT_CONFIG(opengl)
908bool QQuickShaderEffect::isOpenGLShaderEffect() const
909{
910 return m_glImpl != nullptr;
911}
912#endif
913
914QT_END_NAMESPACE
915
916#include "moc_qquickshadereffect_p.cpp"
917

source code of qtdeclarative/src/quick/items/qquickshadereffect.cpp