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 QtOpenGL 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#ifndef QPAINTENGINEEX_OPENGL2_P_H
41#define QPAINTENGINEEX_OPENGL2_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QDebug>
55
56#include <private/qpaintengineex_p.h>
57#include <private/qglengineshadermanager_p.h>
58#include <private/qgl2pexvertexarray_p.h>
59#include <private/qglpaintdevice_p.h>
60#include <private/qfontengine_p.h>
61#include <private/qdatabuffer_p.h>
62#include <private/qtriangulatingstroker_p.h>
63#include <private/qopenglextensions_p.h>
64
65enum EngineMode {
66 ImageDrawingMode,
67 TextDrawingMode,
68 BrushDrawingMode,
69 ImageArrayDrawingMode
70};
71
72QT_BEGIN_NAMESPACE
73
74#define GL_STENCIL_HIGH_BIT GLuint(0x80)
75#define QT_BRUSH_TEXTURE_UNIT GLuint(0)
76#define QT_IMAGE_TEXTURE_UNIT GLuint(0) //Can be the same as brush texture unit
77#define QT_MASK_TEXTURE_UNIT GLuint(1)
78#define QT_BACKGROUND_TEXTURE_UNIT GLuint(2)
79
80class QGL2PaintEngineExPrivate;
81
82
83class QGL2PaintEngineState : public QPainterState
84{
85public:
86 QGL2PaintEngineState(QGL2PaintEngineState &other);
87 QGL2PaintEngineState();
88 ~QGL2PaintEngineState();
89
90 uint isNew : 1;
91 uint needsClipBufferClear : 1;
92 uint clipTestEnabled : 1;
93 uint canRestoreClip : 1;
94 uint matrixChanged : 1;
95 uint compositionModeChanged : 1;
96 uint opacityChanged : 1;
97 uint renderHintsChanged : 1;
98 uint clipChanged : 1;
99 uint currentClip : 8;
100
101 QRect rectangleClip;
102};
103
104class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
105{
106 Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
107public:
108 QGL2PaintEngineEx();
109 ~QGL2PaintEngineEx();
110
111 bool begin(QPaintDevice *device) override;
112 void ensureActive();
113 bool end() override;
114
115 virtual void clipEnabledChanged() override;
116 virtual void penChanged() override;
117 virtual void brushChanged() override;
118 virtual void brushOriginChanged() override;
119 virtual void opacityChanged() override;
120 virtual void compositionModeChanged() override;
121 virtual void renderHintsChanged() override;
122 virtual void transformChanged() override;
123
124 virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
125 virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
126 QPainter::PixmapFragmentHints hints) override;
127 virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
128 Qt::ImageConversionFlags flags = Qt::AutoColor) override;
129 virtual void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
130 virtual void fill(const QVectorPath &path, const QBrush &brush) override;
131 virtual void stroke(const QVectorPath &path, const QPen &pen) override;
132 virtual void clip(const QVectorPath &path, Qt::ClipOperation op) override;
133
134 virtual void drawStaticTextItem(QStaticTextItem *textItem) override;
135
136 bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
137
138 Type type() const override { return OpenGL2; }
139
140 virtual void setState(QPainterState *s) override;
141 virtual QPainterState *createState(QPainterState *orig) const override;
142 inline QGL2PaintEngineState *state() {
143 return static_cast<QGL2PaintEngineState *>(QPaintEngineEx::state());
144 }
145 inline const QGL2PaintEngineState *state() const {
146 return static_cast<const QGL2PaintEngineState *>(QPaintEngineEx::state());
147 }
148
149 void beginNativePainting() override;
150 void endNativePainting() override;
151
152 void invalidateState();
153
154 void setRenderTextActive(bool);
155
156 bool isNativePaintingActive() const;
157 bool requiresPretransformedGlyphPositions(QFontEngine *, const QTransform &) const override { return false; }
158 bool shouldDrawCachedGlyphs(QFontEngine *, const QTransform &) const override;
159
160 void setTranslateZ(GLfloat z);
161
162private:
163 Q_DISABLE_COPY_MOVE(QGL2PaintEngineEx)
164};
165
166class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
167{
168 Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
169public:
170 enum StencilFillMode {
171 OddEvenFillMode,
172 WindingFillMode,
173 TriStripStrokeFillMode
174 };
175
176 QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
177 q(q_ptr),
178 shaderManager(nullptr),
179 width(0), height(0),
180 ctx(nullptr),
181 useSystemClip(true),
182 elementIndicesVBOId(0),
183 opacityArray(0),
184 snapToPixelGrid(false),
185 nativePaintingActive(false),
186 inverseScale(1),
187 lastMaskTextureUsed(0),
188 translateZ(0)
189 { }
190
191 ~QGL2PaintEngineExPrivate();
192
193 void updateBrushTexture();
194 void updateBrushUniforms();
195 void updateMatrix();
196 void updateCompositionMode();
197 void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
198
199 void resetGLState();
200 bool resetOpenGLContextActiveEngine();
201
202 // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
203 // however writeClip can also be thought of as en entry point as it does similar things.
204 void fill(const QVectorPath &path);
205 void stroke(const QVectorPath &path, const QPen &pen);
206 void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
207 void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
208 QPainter::PixmapFragmentHints hints);
209 void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem);
210
211 // Calls glVertexAttributePointer if the pointer has changed
212 inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
213
214 // draws whatever is in the vertex array:
215 void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
216 void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
217 drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
218 }
219
220 // Composites the bounding rect onto dest buffer:
221 void composite(const QGLRect& boundingRect);
222
223 // Calls drawVertexArrays to render into stencil buffer:
224 void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode);
225 void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) {
226 fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
227 vertexArray.boundingRect(),
228 useWindingFill ? WindingFillMode : OddEvenFillMode);
229 }
230
231 void setBrush(const QBrush& brush);
232 void transferMode(EngineMode newMode);
233 bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
234 bool prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache);
235 inline void useSimpleShader();
236 inline GLuint location(const QGLEngineShaderManager::Uniform uniform) {
237 return shaderManager->getUniformLocation(uniform);
238 }
239
240 void clearClip(uint value);
241 void writeClip(const QVectorPath &path, uint value);
242 void resetClipIfNeeded();
243
244 void updateClipScissorTest();
245 void setScissor(const QRect &rect);
246 void regenerateClip();
247 void systemStateChanged() override;
248
249
250 static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
251 static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
252 static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
253
254
255 QGL2PaintEngineEx* q;
256 QGLEngineShaderManager* shaderManager;
257 QGLPaintDevice* device;
258 int width, height;
259 QGLContext *ctx;
260 EngineMode mode;
261 QFontEngine::GlyphFormat glyphCacheFormat;
262
263 // Dirty flags
264 bool matrixDirty; // Implies matrix uniforms are also dirty
265 bool compositionModeDirty;
266 bool brushTextureDirty;
267 bool brushUniformsDirty;
268 bool opacityUniformDirty;
269 bool matrixUniformDirty;
270 bool translateZUniformDirty;
271
272 bool stencilClean; // Has the stencil not been used for clipping so far?
273 bool useSystemClip;
274 QRegion dirtyStencilRegion;
275 QRect currentScissorBounds;
276 uint maxClip;
277
278 QBrush currentBrush; // May not be the state's brush!
279 const QBrush noBrush;
280
281 QPixmap currentBrushPixmap;
282
283 QGL2PEXVertexArray vertexCoordinateArray;
284 QGL2PEXVertexArray textureCoordinateArray;
285 QVector<GLushort> elementIndices;
286 GLuint elementIndicesVBOId;
287 QDataBuffer<GLfloat> opacityArray;
288 GLfloat staticVertexCoordinateArray[8];
289 GLfloat staticTextureCoordinateArray[8];
290
291 bool snapToPixelGrid;
292 bool nativePaintingActive;
293 GLfloat pmvMatrix[3][3];
294 GLfloat inverseScale;
295
296 GLuint lastTextureUsed;
297 GLuint lastMaskTextureUsed;
298
299 bool needsSync;
300 bool multisamplingAlwaysEnabled;
301
302 GLfloat depthRange[2];
303
304 float textureInvertedY;
305
306 QTriangulatingStroker stroker;
307 QDashedStrokeProcessor dasher;
308
309 QSet<QVectorPath::CacheEntry *> pathCaches;
310 QVector<GLuint> unusedVBOSToClean;
311 QVector<GLuint> unusedIBOSToClean;
312
313 const GLfloat *vertexAttribPointers[3];
314
315 GLfloat translateZ;
316};
317
318
319void QGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer)
320{
321 Q_ASSERT(arrayIndex < 3);
322 if (pointer == vertexAttribPointers[arrayIndex])
323 return;
324
325 vertexAttribPointers[arrayIndex] = pointer;
326 if (arrayIndex == QT_OPACITY_ATTR)
327 glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
328 else
329 glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);
330}
331
332QT_END_NAMESPACE
333
334#endif // QPAINTENGINEEX_OPENGL2_P_H
335