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 \section1 Security Considerations
70
71 \warning All content rendered through QOpenGLPaintDevice is expected to be
72 trusted content. Vector geometry, images, and other drawing data are
73 processed, possibly modified, and passed on to the underlying OpenGL
74 implementation. Application developers are advised to carefully consider the
75 potential implications before rendering (passing on) user-provided content.
76
77 \sa {OpenGL Window Example}
78
79*/
80
81/*!
82 Constructs a QOpenGLPaintDevice.
83
84 The QOpenGLPaintDevice is only valid for the current context.
85
86 \sa QOpenGLContext::currentContext()
87*/
88QOpenGLPaintDevice::QOpenGLPaintDevice()
89 : d_ptr(new QOpenGLPaintDevicePrivate(QSize()))
90{
91}
92
93/*!
94 Constructs a QOpenGLPaintDevice with the given \a size.
95
96 The QOpenGLPaintDevice is only valid for the current context.
97
98 \sa QOpenGLContext::currentContext()
99*/
100QOpenGLPaintDevice::QOpenGLPaintDevice(const QSize &size)
101 : d_ptr(new QOpenGLPaintDevicePrivate(size))
102{
103}
104
105/*!
106 Constructs a QOpenGLPaintDevice with the given \a width and \a height.
107
108 The QOpenGLPaintDevice is only valid for the current context.
109
110 \sa QOpenGLContext::currentContext()
111*/
112QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height)
113 : QOpenGLPaintDevice(QSize(width, height))
114{
115}
116
117/*!
118 \internal
119 */
120QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd)
121 : d_ptr(&dd)
122{
123}
124
125/*!
126 Destroys the QOpenGLPaintDevice.
127*/
128
129QOpenGLPaintDevice::~QOpenGLPaintDevice()
130{
131 delete d_ptr->engine;
132}
133
134/*!
135 \fn int QOpenGLPaintDevice::devType() const
136 \internal
137 \reimp
138*/
139
140QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz)
141 : size(sz)
142 , ctx(QOpenGLContext::currentContext())
143 , dpmx(qt_defaultDpiX() * 100. / 2.54)
144 , dpmy(qt_defaultDpiY() * 100. / 2.54)
145 , devicePixelRatio(1.0)
146 , flipped(false)
147 , engine(nullptr)
148{
149}
150
151QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate()
152{
153}
154
156{
157public:
159 QPaintEngine *&localEngine = storage.localData();
160 if (!localEngine)
161 localEngine = new QOpenGL2PaintEngineEx;
162 return localEngine;
163 }
164
165private:
166 QThreadStorage<QPaintEngine *> storage;
167};
168
169Q_GLOBAL_STATIC(QOpenGLEngineThreadStorage, qt_opengl_engine)
170
171/*!
172 \reimp
173*/
174
175QPaintEngine *QOpenGLPaintDevice::paintEngine() const
176{
177 if (d_ptr->engine)
178 return d_ptr->engine;
179
180 QPaintEngine *engine = qt_opengl_engine()->engine();
181 if (engine->isActive() && engine->paintDevice() != this) {
182 d_ptr->engine = new QOpenGL2PaintEngineEx;
183 return d_ptr->engine;
184 }
185
186 return engine;
187}
188
189/*!
190 Returns the OpenGL context associated with the paint device.
191*/
192
193QOpenGLContext *QOpenGLPaintDevice::context() const
194{
195 return d_ptr->ctx;
196}
197
198/*!
199 Returns the pixel size of the paint device.
200
201 \sa setSize()
202*/
203
204QSize QOpenGLPaintDevice::size() const
205{
206 return d_ptr->size;
207}
208
209/*!
210 Sets the pixel size of the paint device to \a size.
211
212 \sa size()
213*/
214
215void QOpenGLPaintDevice::setSize(const QSize &size)
216{
217 d_ptr->size = size;
218}
219
220/*!
221 Sets the device pixel ratio for the paint device to \a devicePixelRatio.
222*/
223void QOpenGLPaintDevice::setDevicePixelRatio(qreal devicePixelRatio)
224{
225 d_ptr->devicePixelRatio = devicePixelRatio;
226}
227
228/*!
229 \reimp
230*/
231
232int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
233{
234 switch (metric) {
235 case PdmWidth:
236 return d_ptr->size.width();
237 case PdmHeight:
238 return d_ptr->size.height();
239 case PdmDepth:
240 return 32;
241 case PdmWidthMM:
242 return qRound(d_ptr->size.width() * 1000 / d_ptr->dpmx);
243 case PdmHeightMM:
244 return qRound(d_ptr->size.height() * 1000 / d_ptr->dpmy);
245 case PdmNumColors:
246 return 0;
247 case PdmDpiX:
248 return qRound(d_ptr->dpmx * 0.0254);
249 case PdmDpiY:
250 return qRound(d_ptr->dpmy * 0.0254);
251 case PdmPhysicalDpiX:
252 return qRound(d_ptr->dpmx * 0.0254);
253 case PdmPhysicalDpiY:
254 return qRound(d_ptr->dpmy * 0.0254);
255 case PdmDevicePixelRatio:
256 return d_ptr->devicePixelRatio;
257 case PdmDevicePixelRatioScaled:
258 return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
259 case PdmDevicePixelRatioF_EncodedA:
260 Q_FALLTHROUGH();
261 case PdmDevicePixelRatioF_EncodedB:
262 return QPaintDevice::encodeMetricF(metric, d_ptr->devicePixelRatio);
263
264 default:
265 qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
266 return 0;
267 }
268}
269
270/*!
271 Returns the number of pixels per meter horizontally.
272
273 \sa setDotsPerMeterX()
274*/
275
276qreal QOpenGLPaintDevice::dotsPerMeterX() const
277{
278 return d_ptr->dpmx;
279}
280
281/*!
282 Returns the number of pixels per meter vertically.
283
284 \sa setDotsPerMeterY()
285*/
286
287qreal QOpenGLPaintDevice::dotsPerMeterY() const
288{
289 return d_ptr->dpmy;
290}
291
292/*!
293 Sets the number of pixels per meter horizontally to \a dpmx.
294
295 \sa dotsPerMeterX()
296*/
297
298void QOpenGLPaintDevice::setDotsPerMeterX(qreal dpmx)
299{
300 d_ptr->dpmx = dpmx;
301}
302
303/*!
304 Sets the number of pixels per meter vertically to \a dpmy.
305
306 \sa dotsPerMeterY()
307*/
308
309void QOpenGLPaintDevice::setDotsPerMeterY(qreal dpmy)
310{
311 d_ptr->dpmy = dpmy;
312}
313
314/*!
315 Sets whether painting should be flipped around the Y-axis or not to \a flipped.
316
317 \sa paintFlipped()
318*/
319void QOpenGLPaintDevice::setPaintFlipped(bool flipped)
320{
321 d_ptr->flipped = flipped;
322}
323
324/*!
325 Returns \c true if painting is flipped around the Y-axis.
326
327 \sa setPaintFlipped()
328*/
329
330bool QOpenGLPaintDevice::paintFlipped() const
331{
332 return d_ptr->flipped;
333}
334
335/*!
336 This virtual method is provided as a callback to allow re-binding a target
337 frame buffer object or context when different QOpenGLPaintDevice instances
338 are issuing draw calls alternately.
339
340 \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger
341 this method.
342
343 The default implementation does nothing.
344*/
345void QOpenGLPaintDevice::ensureActiveTarget()
346{
347}
348
349QT_END_NAMESPACE
Combined button and popup list for selecting options.