1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QOPENGLPAINTENGINE_P_H
43 #define QOPENGLPAINTENGINE_P_H
49 // This file is not part of the Qt API. It exists purely as an
50 // implementation detail. This header file may change from version to
51 // version without notice, or even be removed.
58 #include <qopenglpaintdevice.h>
60 #include <private/qpaintengineex_p.h>
61 #include <private/qopenglengineshadermanager_p.h>
62 #include <private/qopengl2pexvertexarray_p.h>
63 #include <private/qfontengine_p.h>
64 #include <private/qdatabuffer_p.h>
65 #include <private/qtriangulatingstroker_p.h>
67 #include <private/qopenglextensions_p.h>
78 #define GL_STENCIL_HIGH_BIT GLuint(0x80)
79 #define QT_BRUSH_TEXTURE_UNIT GLuint(0)
80 #define QT_IMAGE_TEXTURE_UNIT GLuint(0) //Can be the same as brush texture unit
81 #define QT_MASK_TEXTURE_UNIT GLuint(1)
82 #define QT_BACKGROUND_TEXTURE_UNIT GLuint(2)
84 class QOpenGL2PaintEngineExPrivate;
86 class QOpenGL2PaintEngineState : public QPainterState
89 QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other);
90 QOpenGL2PaintEngineState();
91 ~QOpenGL2PaintEngineState();
94 uint needsClipBufferClear : 1;
95 uint clipTestEnabled : 1;
96 uint canRestoreClip : 1;
97 uint matrixChanged : 1;
98 uint compositionModeChanged : 1;
99 uint opacityChanged : 1;
100 uint renderHintsChanged : 1;
101 uint clipChanged : 1;
102 uint currentClip : 8;
107 class Q_GUI_EXPORT QOpenGL2PaintEngineEx : public QPaintEngineEx
109 Q_DECLARE_PRIVATE(QOpenGL2PaintEngineEx)
111 QOpenGL2PaintEngineEx();
112 ~QOpenGL2PaintEngineEx();
114 bool begin(QPaintDevice *device);
118 virtual void clipEnabledChanged();
119 virtual void penChanged();
120 virtual void brushChanged();
121 virtual void brushOriginChanged();
122 virtual void opacityChanged();
123 virtual void compositionModeChanged();
124 virtual void renderHintsChanged();
125 virtual void transformChanged();
127 virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
128 virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
129 QPainter::PixmapFragmentHints hints);
130 virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
131 Qt::ImageConversionFlags flags = Qt::AutoColor);
132 virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
133 virtual void fill(const QVectorPath &path, const QBrush &brush);
134 virtual void stroke(const QVectorPath &path, const QPen &pen);
135 virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
137 virtual void drawStaticTextItem(QStaticTextItem *textItem);
139 bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
141 Type type() const { return OpenGL2; }
143 virtual void setState(QPainterState *s);
144 virtual QPainterState *createState(QPainterState *orig) const;
145 inline QOpenGL2PaintEngineState *state() {
146 return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
148 inline const QOpenGL2PaintEngineState *state() const {
149 return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
152 void beginNativePainting();
153 void endNativePainting();
155 void invalidateState();
157 void setRenderTextActive(bool);
159 bool isNativePaintingActive() const;
160 bool supportsTransformations(QFontEngine *, const QTransform &) const { return true; }
163 Q_DISABLE_COPY(QOpenGL2PaintEngineEx)
165 friend class QOpenGLEngineShaderManager;
168 // This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
169 // all the GL2 engine uses:
170 #define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
172 class QOpenGL2PaintEngineExPrivate : public QPaintEngineExPrivate
174 Q_DECLARE_PUBLIC(QOpenGL2PaintEngineEx)
176 enum StencilFillMode {
179 TriStripStrokeFillMode
182 QOpenGL2PaintEngineExPrivate(QOpenGL2PaintEngineEx *q_ptr) :
188 elementIndicesVBOId(0),
190 snapToPixelGrid(false),
191 nativePaintingActive(false),
193 lastMaskTextureUsed(0)
196 ~QOpenGL2PaintEngineExPrivate();
198 void updateBrushTexture();
199 void updateBrushUniforms();
201 void updateCompositionMode();
202 void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
206 // fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
207 // however writeClip can also be thought of as en entry point as it does similar things.
208 void fill(const QVectorPath &path);
209 void stroke(const QVectorPath &path, const QPen &pen);
210 void drawTexture(const QOpenGLRect& dest, const QOpenGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
211 void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
212 QPainter::PixmapFragmentHints hints);
213 void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem);
215 // Calls glVertexAttributePointer if the pointer has changed
216 inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
218 // draws whatever is in the vertex array:
219 void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
220 void drawVertexArrays(QOpenGL2PEXVertexArray &vertexArray, GLenum primitive) {
221 drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
224 // Composites the bounding rect onto dest buffer:
225 void composite(const QOpenGLRect& boundingRect);
227 // Calls drawVertexArrays to render into stencil buffer:
228 void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QOpenGLRect &bounds, StencilFillMode mode);
229 void fillStencilWithVertexArray(QOpenGL2PEXVertexArray& vertexArray, bool useWindingFill) {
230 fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
231 vertexArray.boundingRect(),
232 useWindingFill ? WindingFillMode : OddEvenFillMode);
235 void setBrush(const QBrush& brush);
236 void transferMode(EngineMode newMode);
237 bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
238 inline void useSimpleShader();
239 inline GLuint location(const QOpenGLEngineShaderManager::Uniform uniform) {
240 return shaderManager->getUniformLocation(uniform);
243 void clearClip(uint value);
244 void writeClip(const QVectorPath &path, uint value);
245 void resetClipIfNeeded();
247 void updateClipScissorTest();
248 void setScissor(const QRect &rect);
249 void regenerateClip();
250 void systemStateChanged();
252 void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
255 static QOpenGLEngineShaderManager* shaderManagerForEngine(QOpenGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
256 static QOpenGL2PaintEngineExPrivate *getData(QOpenGL2PaintEngineEx *engine) { return engine->d_func(); }
257 static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
259 QOpenGLExtensions funcs;
261 QOpenGL2PaintEngineEx* q;
262 QOpenGLEngineShaderManager* shaderManager;
263 QOpenGLPaintDevice* device;
267 QFontEngineGlyphCache::Type glyphCacheType;
269 bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
272 bool matrixDirty; // Implies matrix uniforms are also dirty
273 bool compositionModeDirty;
274 bool brushTextureDirty;
275 bool brushUniformsDirty;
276 bool opacityUniformDirty;
277 bool matrixUniformDirty;
279 bool stencilClean; // Has the stencil not been used for clipping so far?
281 QRegion dirtyStencilRegion;
282 QRect currentScissorBounds;
285 QBrush currentBrush; // May not be the state's brush!
286 const QBrush noBrush;
288 QPixmap currentBrushPixmap;
290 QOpenGL2PEXVertexArray vertexCoordinateArray;
291 QOpenGL2PEXVertexArray textureCoordinateArray;
292 QVector<GLushort> elementIndices;
293 GLuint elementIndicesVBOId;
294 QDataBuffer<GLfloat> opacityArray;
295 GLfloat staticVertexCoordinateArray[8];
296 GLfloat staticTextureCoordinateArray[8];
298 bool snapToPixelGrid;
299 bool nativePaintingActive;
300 GLfloat pmvMatrix[3][3];
301 GLfloat inverseScale;
303 GLuint lastTextureUsed;
304 GLuint lastMaskTextureUsed;
307 bool multisamplingAlwaysEnabled;
309 GLfloat depthRange[2];
311 float textureInvertedY;
313 QTriangulatingStroker stroker;
314 QDashedStrokeProcessor dasher;
316 QSet<QVectorPath::CacheEntry *> pathCaches;
317 QVector<GLuint> unusedVBOSToClean;
318 QVector<GLuint> unusedIBOSToClean;
320 const GLfloat *vertexAttribPointers[3];
324 void QOpenGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer)
326 Q_ASSERT(arrayIndex < 3);
327 if (pointer == vertexAttribPointers[arrayIndex])
330 vertexAttribPointers[arrayIndex] = pointer;
331 if (arrayIndex == QT_OPACITY_ATTR)
332 funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
334 funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);