Qt 4.8
shadereffect.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QML Shaders plugin 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "shadereffect.h"
43 #include "shadereffectbuffer.h"
44 #include "shadereffectsource.h"
45 
46 #include <QDeclarativeItem>
47 #include <QPainter>
48 #include <QtOpenGL>
49 
51 
53  : QGraphicsEffect(parent)
54  , m_changed(true)
55 {
56 }
57 
59 {
60 }
61 
63 {
64 #ifndef QT_NO_DYNAMIC_CAST
65  // This workaround needed because QGraphicsEffect seems to always utilize default painters worldtransform
66  // instead of the active painters worldtransform.
67  const ShaderEffectBuffer *effectBuffer = dynamic_cast<ShaderEffectBuffer*> (painter->device());
68  if (effectBuffer) {
69  savedWorldTransform = painter->worldTransform() * savedWorldTransform;
70  painter->setWorldTransform(savedWorldTransform);
71  } else {
72  savedWorldTransform = painter->worldTransform();
73  }
74 #else
75  Q_UNUSED(painter);
76 #endif
77 }
78 
80 {
81  const QGLContext *context = QGLContext::currentContext();
82 
83  prepareBufferedDraw(painter);
84 
85  if (context) {
87  }
88 
89  if (!context || m_renderTargets.count() == 0 || !hideOriginal())
90  drawSource(painter);
91 }
92 
94 {
95  if (!m_changed)
96  return;
97 
98  m_changed = false;
99 
100  int count = m_renderTargets.count();
101  for (int i = 0; i < count; i++) {
102  if (m_renderTargets[i]->isLive() || m_renderTargets[i]->isDirtyTexture()) {
103  m_renderTargets[i]->updateBackbuffer();
104  ShaderEffectBuffer* target = m_renderTargets[i]->fbo();
105  if (target && target->isValid() && target->width() > 0 && target->height() > 0) {
106  QPainter p(target);
108  p.fillRect(QRect(QPoint(0, 0), target->size()), Qt::transparent);
110 
111  QRectF sourceRect = m_renderTargets[i]->sourceRect();
112  QSize textureSize = m_renderTargets[i]->textureSize();
113 
114  qreal yflip = m_renderTargets[i]->isMirrored() ? -1.0 : 1.0; // flip y to match scenegraph, it also flips texturecoordinates
115  qreal xscale = 1.0;
116  qreal yscale = 1.0 * yflip;
117 
118  qreal leftMargin = 0.0;
119  qreal rightMargin = 0.0;
120  qreal topMargin = 0.0;
121  qreal bottomMargin = 0.0;
122 
123  qreal width = m_renderTargets[i]->sourceItem()->width();
124  qreal height = m_renderTargets[i]->sourceItem()->height();
125 
126  if (!sourceRect.isEmpty()) {
127  leftMargin = -sourceRect.left();
128  rightMargin = sourceRect.right() - width;
129  topMargin = -sourceRect.top();
130  bottomMargin = sourceRect.bottom() - height;
131  }
132 
133  if ((width + leftMargin + rightMargin) > 0 && (height + topMargin + bottomMargin) > 0) {
134  if (!textureSize.isEmpty()) {
135  qreal textureWidth = textureSize.width();
136  qreal textureHeight = textureSize.height();
137 
138  xscale = width / (width + leftMargin + rightMargin);
139  yscale = height / (height + topMargin + bottomMargin);
140 
141  p.translate(textureWidth / 2, textureHeight / 2);
142  p.scale(xscale, yscale * yflip);
143  p.translate(-textureWidth / 2, -textureHeight / 2);
144  p.scale(textureWidth / width, textureHeight / height);
145  } else {
146  xscale = width / (width + leftMargin + rightMargin);
147  yscale = height / (height + topMargin + bottomMargin);
148 
149  p.translate(width / 2, height / 2);
150  p.scale(xscale, yscale * yflip);
151  p.translate(-width / 2, -height / 2);
152  }
153  }
154 
155  drawSource(&p);
156  p.end();
157  m_renderTargets[i]->markSceneGraphDirty();
158  }
159  }
160  }
161 }
162 
163 void ShaderEffect::sourceChanged (ChangeFlags flags)
164 {
165  Q_UNUSED(flags);
166  m_changed = true;
167 }
168 
170 {
171  if (!m_renderTargets.contains(target))
172  m_renderTargets.append(target);
173 }
174 
176 {
177  int index = m_renderTargets.indexOf(target);
178  if (index >= 0)
179  m_renderTargets.remove(index);
180  else
181  qWarning() << "ShaderEffect::removeRenderTarget - did not find target.";
182 }
183 
185 {
186  if (m_renderTargets.count() == 0)
187  return false;
188 
189  // Just like scenegraph version, if there is even one source that says "hide original" we hide it.
190  int count = m_renderTargets.count();
191  for (int i = 0; i < count; i++) {
192  if (m_renderTargets[i]->hideSource())
193  return true;
194  }
195  return false;
196 }
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
QPaintDevice * device() const
Returns the paint device on which this painter is currently painting, or 0 if the painter is not acti...
Definition: qpainter.cpp:1530
QSize size() const
Returns the size of the texture attached to this framebuffer object.
static QTransform savedWorldTransform
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
bool hideOriginal() const
double qreal
Definition: qglobal.h:1193
void remove(int i)
Removes the element at index position i.
Definition: qvector.h:374
int count(const T &t) const
Returns the number of occurrences of value in the vector.
Definition: qvector.h:742
bool isValid() const
Returns true if the framebuffer object is valid.
int height() const
Definition: qpaintdevice.h:92
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
void drawSource(QPainter *painter)
Draws the source directly using the given painter.
virtual void draw(QPainter *painter)
This pure virtual function draws the effect and is called whenever the source needs to be drawn...
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void addRenderTarget(ShaderEffectSource *target)
static const QGLContext * currentContext()
Returns the current context, i.e.
Definition: qgl.cpp:3545
ShaderEffect(QObject *parent=0)
int width() const
Returns the width.
Definition: qsize.h:126
int width() const
Definition: qpaintdevice.h:91
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
The QGLContext class encapsulates an OpenGL rendering context.
Definition: qgl.h:310
virtual void sourceChanged(ChangeFlags flags)
This virtual function is called by QGraphicsEffect to notify the effect that the source has changed...
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
Q_CORE_EXPORT void qWarning(const char *,...)
void prepareBufferedDraw(QPainter *painter)
void updateRenderTargets()
int indexOf(const T &t, int from=0) const
Returns the index position of the first occurrence of value in the vector, searching forward from ind...
Definition: qvector.h:698
The ShaderEffectSource object encapsulates the source content for the ShaderEffectItem.
QVector< ShaderEffectSource * > m_renderTargets
Definition: shadereffect.h:73
const QTransform & worldTransform() const
Returns the world transformation matrix.
Definition: qpainter.cpp:9652
void setCompositionMode(CompositionMode mode)
Sets the composition mode to the given mode.
Definition: qpainter.cpp:2422
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
void setWorldTransform(const QTransform &matrix, bool combine=false)
Sets the world transformation matrix.
Definition: qpainter.cpp:9630
bool contains(const T &t) const
Returns true if the vector contains an occurrence of value; otherwise returns false.
Definition: qvector.h:731
void removeRenderTarget(ShaderEffectSource *target)
quint16 index
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
void scale(qreal sx, qreal sy)
Scales the coordinate system by ({sx}, {sy}).
Definition: qpainter.cpp:3234
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
bool isEmpty() const
Returns true if either of the width and height is less than or equal to 0; otherwise returns false...
Definition: qsize.h:120
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:658
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
bool end()
Ends painting.
Definition: qpainter.cpp:1929
void fillRect(const QRectF &, const QBrush &)
Fills the given rectangle with the brush specified.
Definition: qpainter.cpp:7420
The QGraphicsEffect class is the base class for all graphics effects.
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
void translate(const QPointF &offset)
Translates the coordinate system by the given offset; i.e.
Definition: qpainter.cpp:3311