Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qopenglpaintdevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <qopenglpaintdevice.h>
6#include <qpaintengine.h>
7#include <qthreadstorage.h>
8
9#include <private/qopenglpaintdevice_p.h>
10#include <private/qobject_p.h>
11#include <private/qopenglcontext_p.h>
12#include <private/qopenglframebufferobject_p.h>
13#include <private/qopenglpaintengine_p.h>
14
15// for qt_defaultDpiX/Y
16#include <private/qfont_p.h>
17
18#include <qopenglfunctions.h>
19
21
22/*!
23 \class QOpenGLPaintDevice
24 \brief The QOpenGLPaintDevice class enables painting to an OpenGL context using QPainter.
25 \since 5.0
26 \inmodule QtOpenGL
27
28 \ingroup painting-3D
29
30 The QOpenGLPaintDevice uses the \b current QOpenGL context to render
31 QPainter draw commands. The context is captured upon construction. It
32 requires support for OpenGL (ES) 2.0 or higher.
33
34 \section1 Performance
35
36 The QOpenGLPaintDevice is almost always hardware accelerated and
37 has the potential of being much faster than software
38 rasterization. However, it is more sensitive to state changes, and
39 therefore requires the drawing commands to be carefully ordered to
40 achieve optimal performance.
41
42 \section1 Antialiasing and Quality
43
44 Antialiasing in the OpenGL paint engine is done using
45 multisampling. Most hardware require significantly more memory to
46 do multisampling and the resulting quality is not on par with the
47 quality of the software paint engine. The OpenGL paint engine's
48 strength lies in its performance, not its visual rendering
49 quality.
50
51 \section1 State Changes
52
53 When painting to a QOpenGLPaintDevice using QPainter, the state of
54 the current OpenGL context will be altered by the paint engine to
55 reflect its needs. Applications should not rely upon the OpenGL
56 state being reset to its original conditions, particularly the
57 current shader program, OpenGL viewport, texture units, and
58 drawing modes.
59
60 \section1 Mixing QPainter and OpenGL
61
62 When intermixing QPainter and OpenGL, it is important to notify
63 QPainter that the OpenGL state may have been cluttered so it can
64 restore its internal state. This is achieved by calling \l
65 QPainter::beginNativePainting() before starting the OpenGL
66 rendering and calling \l QPainter::endNativePainting() after
67 finishing.
68
69 \sa {OpenGL Window Example}
70
71*/
72
73/*!
74 Constructs a QOpenGLPaintDevice.
75
76 The QOpenGLPaintDevice is only valid for the current context.
77
78 \sa QOpenGLContext::currentContext()
79*/
80QOpenGLPaintDevice::QOpenGLPaintDevice()
81 : d_ptr(new QOpenGLPaintDevicePrivate(QSize()))
82{
83}
84
85/*!
86 Constructs a QOpenGLPaintDevice with the given \a size.
87
88 The QOpenGLPaintDevice is only valid for the current context.
89
90 \sa QOpenGLContext::currentContext()
91*/
92QOpenGLPaintDevice::QOpenGLPaintDevice(const QSize &size)
93 : d_ptr(new QOpenGLPaintDevicePrivate(size))
94{
95}
96
97/*!
98 Constructs a QOpenGLPaintDevice with the given \a width and \a height.
99
100 The QOpenGLPaintDevice is only valid for the current context.
101
102 \sa QOpenGLContext::currentContext()
103*/
104QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height)
105 : QOpenGLPaintDevice(QSize(width, height))
106{
107}
108
109/*!
110 \internal
111 */
112QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd)
113 : d_ptr(&dd)
114{
115}
116
117/*!
118 Destroys the QOpenGLPaintDevice.
119*/
120
121QOpenGLPaintDevice::~QOpenGLPaintDevice()
122{
123 delete d_ptr->engine;
124}
125
126/*!
127 \fn int QOpenGLPaintDevice::devType() const
128 \internal
129 \reimp
130*/
131
132QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz)
133 : size(sz)
134 , ctx(QOpenGLContext::currentContext())
135 , dpmx(qt_defaultDpiX() * 100. / 2.54)
136 , dpmy(qt_defaultDpiY() * 100. / 2.54)
137 , devicePixelRatio(1.0)
138 , flipped(false)
139 , engine(nullptr)
140{
141}
142
143QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate()
144{
145}
146
148{
149public:
151 QPaintEngine *&localEngine = storage.localData();
152 if (!localEngine)
153 localEngine = new QOpenGL2PaintEngineEx;
154 return localEngine;
155 }
156
157private:
158 QThreadStorage<QPaintEngine *> storage;
159};
160
161Q_GLOBAL_STATIC(QOpenGLEngineThreadStorage, qt_opengl_engine)
162
163/*!
164 \reimp
165*/
166
167QPaintEngine *QOpenGLPaintDevice::paintEngine() const
168{
169 if (d_ptr->engine)
170 return d_ptr->engine;
171
172 QPaintEngine *engine = qt_opengl_engine()->engine();
173 if (engine->isActive() && engine->paintDevice() != this) {
174 d_ptr->engine = new QOpenGL2PaintEngineEx;
175 return d_ptr->engine;
176 }
177
178 return engine;
179}
180
181/*!
182 Returns the OpenGL context associated with the paint device.
183*/
184
185QOpenGLContext *QOpenGLPaintDevice::context() const
186{
187 return d_ptr->ctx;
188}
189
190/*!
191 Returns the pixel size of the paint device.
192
193 \sa setSize()
194*/
195
196QSize QOpenGLPaintDevice::size() const
197{
198 return d_ptr->size;
199}
200
201/*!
202 Sets the pixel size of the paint device to \a size.
203
204 \sa size()
205*/
206
207void QOpenGLPaintDevice::setSize(const QSize &size)
208{
209 d_ptr->size = size;
210}
211
212/*!
213 Sets the device pixel ratio for the paint device to \a devicePixelRatio.
214*/
215void QOpenGLPaintDevice::setDevicePixelRatio(qreal devicePixelRatio)
216{
217 d_ptr->devicePixelRatio = devicePixelRatio;
218}
219
220/*!
221 \reimp
222*/
223
224int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
225{
226 switch (metric) {
227 case PdmWidth:
228 return d_ptr->size.width();
229 case PdmHeight:
230 return d_ptr->size.height();
231 case PdmDepth:
232 return 32;
233 case PdmWidthMM:
234 return qRound(d_ptr->size.width() * 1000 / d_ptr->dpmx);
235 case PdmHeightMM:
236 return qRound(d_ptr->size.height() * 1000 / d_ptr->dpmy);
237 case PdmNumColors:
238 return 0;
239 case PdmDpiX:
240 return qRound(d_ptr->dpmx * 0.0254);
241 case PdmDpiY:
242 return qRound(d_ptr->dpmy * 0.0254);
243 case PdmPhysicalDpiX:
244 return qRound(d_ptr->dpmx * 0.0254);
245 case PdmPhysicalDpiY:
246 return qRound(d_ptr->dpmy * 0.0254);
247 case PdmDevicePixelRatio:
248 return d_ptr->devicePixelRatio;
249 case PdmDevicePixelRatioScaled:
250 return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
251 case PdmDevicePixelRatioF_EncodedA:
252 Q_FALLTHROUGH();
253 case PdmDevicePixelRatioF_EncodedB:
254 return QPaintDevice::encodeMetricF(metric, d_ptr->devicePixelRatio);
255
256 default:
257 qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
258 return 0;
259 }
260}
261
262/*!
263 Returns the number of pixels per meter horizontally.
264
265 \sa setDotsPerMeterX()
266*/
267
268qreal QOpenGLPaintDevice::dotsPerMeterX() const
269{
270 return d_ptr->dpmx;
271}
272
273/*!
274 Returns the number of pixels per meter vertically.
275
276 \sa setDotsPerMeterY()
277*/
278
279qreal QOpenGLPaintDevice::dotsPerMeterY() const
280{
281 return d_ptr->dpmy;
282}
283
284/*!
285 Sets the number of pixels per meter horizontally to \a dpmx.
286
287 \sa dotsPerMeterX()
288*/
289
290void QOpenGLPaintDevice::setDotsPerMeterX(qreal dpmx)
291{
292 d_ptr->dpmx = dpmx;
293}
294
295/*!
296 Sets the number of pixels per meter vertically to \a dpmy.
297
298 \sa dotsPerMeterY()
299*/
300
301void QOpenGLPaintDevice::setDotsPerMeterY(qreal dpmy)
302{
303 d_ptr->dpmy = dpmy;
304}
305
306/*!
307 Sets whether painting should be flipped around the Y-axis or not to \a flipped.
308
309 \sa paintFlipped()
310*/
311void QOpenGLPaintDevice::setPaintFlipped(bool flipped)
312{
313 d_ptr->flipped = flipped;
314}
315
316/*!
317 Returns \c true if painting is flipped around the Y-axis.
318
319 \sa setPaintFlipped()
320*/
321
322bool QOpenGLPaintDevice::paintFlipped() const
323{
324 return d_ptr->flipped;
325}
326
327/*!
328 This virtual method is provided as a callback to allow re-binding a target
329 frame buffer object or context when different QOpenGLPaintDevice instances
330 are issuing draw calls alternately.
331
332 \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger
333 this method.
334
335 The default implementation does nothing.
336*/
337void QOpenGLPaintDevice::ensureActiveTarget()
338{
339}
340
341QT_END_NAMESPACE
Combined button and popup list for selecting options.