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 
65 enum EngineMode {
66     ImageDrawingMode,
67     TextDrawingMode,
68     BrushDrawingMode,
69     ImageArrayDrawingMode
70 };
71 
72 QT_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 
80 class QGL2PaintEngineExPrivate;
81 
82 
83 class QGL2PaintEngineState : public QPainterState
84 {
85 public:
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 
104 class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
105 {
106     Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
107 public:
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 
type()138     Type type() const override { return OpenGL2; }
139 
140     virtual void setState(QPainterState *s) override;
141     virtual QPainterState *createState(QPainterState *orig) const override;
state()142     inline QGL2PaintEngineState *state() {
143         return static_cast<QGL2PaintEngineState *>(QPaintEngineEx::state());
144     }
state()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;
requiresPretransformedGlyphPositions(QFontEngine *,const QTransform &)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 
162 private:
163     Q_DISABLE_COPY_MOVE(QGL2PaintEngineEx)
164 };
165 
166 class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
167 {
168     Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
169 public:
170     enum StencilFillMode {
171         OddEvenFillMode,
172         WindingFillMode,
173         TriStripStrokeFillMode
174     };
175 
QGL2PaintEngineExPrivate(QGL2PaintEngineEx * q_ptr)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);
drawVertexArrays(QGL2PEXVertexArray & vertexArray,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);
fillStencilWithVertexArray(QGL2PEXVertexArray & vertexArray,bool useWindingFill)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();
location(const QGLEngineShaderManager::Uniform uniform)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 
shaderManagerForEngine(QGL2PaintEngineEx * engine)250     static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
getData(QGL2PaintEngineEx * engine)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 
setVertexAttributePointer(unsigned int arrayIndex,const GLfloat * pointer)319 void 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 
332 QT_END_NAMESPACE
333 
334 #endif // QPAINTENGINEEX_OPENGL2_P_H
335