Qwt User's Guide 6.3.0
Loading...
Searching...
No Matches
qwt_plot_opengl_canvas.cpp
1/******************************************************************************
2 * Qwt Widget Library
3 * Copyright (C) 1997 Josef Wilgen
4 * Copyright (C) 2002 Uwe Rathmann
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the Qwt License, Version 1.0
8 *****************************************************************************/
9
10#include "qwt_plot_opengl_canvas.h"
11#include "qwt_plot.h"
12#include "qwt_painter.h"
13
14#include <qpainter.h>
15#include <qpainterpath.h>
16#include <qcoreevent.h>
17#include <qopenglframebufferobject.h>
18#include <qopenglpaintdevice.h>
19
20class QwtPlotOpenGLCanvas::PrivateData
21{
22 public:
23 PrivateData()
24 : numFBOSamples( -1 )
25 , isPolished( false )
26 , fboDirty( true )
27 , fbo( NULL )
28 {
29 }
30
31 ~PrivateData()
32 {
33 delete fbo;
34 }
35
36 int numFBOSamples;
37
38 bool isPolished;
39 bool fboDirty;
40 QOpenGLFramebufferObject* fbo;
41};
42
50 : QOpenGLWidget( plot )
52{
53 init();
54}
55
64 : QOpenGLWidget( plot )
66{
67 if ( numSamples < -1 )
68 numSamples = -1;
69
70 QSurfaceFormat fmt = format();
71 if ( numSamples != fmt.samples() )
72 {
73 fmt.setSamples( numSamples );
74 setFormat( fmt );
75 }
76
77 init();
78}
79
80void QwtPlotOpenGLCanvas::init()
81{
82 m_data = new PrivateData;
83
84#if 1
85 setAttribute( Qt::WA_OpaquePaintEvent, true );
86#endif
87
88 setLineWidth( 2 );
89 setFrameShadow( QFrame::Sunken );
90 setFrameShape( QFrame::Panel );
91}
92
98
105void QwtPlotOpenGLCanvas::paintEvent( QPaintEvent* event )
106{
107 if ( m_data->isPolished )
108 QOpenGLWidget::paintEvent( event );
109}
110
116bool QwtPlotOpenGLCanvas::event( QEvent* event )
117{
118 if ( event->type() == QEvent::Resize )
119 {
120 if ( m_data->numFBOSamples < 0 )
121 {
122 /*
123 QOpenGLWidget always uses a FBO and sets the number of samples for
124 the FBO not for the widget itself. So format().samples() does not
125 return the correct value after the first QEvent::Resize.
126 */
127 m_data->numFBOSamples = qMax( format().samples(), 0 );
128 }
129 }
130
131 const bool ok = QOpenGLWidget::event( event );
132
133 if ( event->type() == QEvent::PolishRequest )
134 {
135 // In opposite to non OpenGL widgets receive pointless
136 // early repaints. As we always have a QEvent::PolishRequest
137 // followed by QEvent::Paint, we can ignore all these repaints.
138
139 m_data->isPolished = true;
140 }
141
142 if ( event->type() == QEvent::PolishRequest ||
143 event->type() == QEvent::StyleChange )
144 {
145 // assuming, that we always have a styled background
146 // when we have a style sheet
147
148 setAttribute( Qt::WA_StyledBackground,
149 testAttribute( Qt::WA_StyleSheet ) );
150 }
151
152 return ok;
153}
154
163
166{
167 m_data->fboDirty = true;
168}
169
170void QwtPlotOpenGLCanvas::clearBackingStore()
171{
172 delete m_data->fbo;
173 m_data->fbo = NULL;
174}
175
185QPainterPath QwtPlotOpenGLCanvas::borderPath( const QRect& rect ) const
186{
187 return canvasBorderPath( rect );
188}
189
194
197{
198 const bool hasFocusIndicator =
199 hasFocus() && focusIndicator() == CanvasFocusIndicator;
200
201 QPainter painter;
202
204 QOpenGLFramebufferObject::hasOpenGLFramebufferBlit() )
205 {
206 const qreal pixelRatio = QwtPainter::devicePixelRatio( this );
207 const QSize fboSize = size() * pixelRatio;
208
209 if ( hasFocusIndicator )
210 painter.begin( this );
211
212 /*
213 QOpenGLWidget has its own internal FBO, that is used to restore
214 its content without having to repaint. This works fine when f.e
215 a rubberband is moving on top, but there are still situations,
216 where we can repaint without an potentially expensive replot:
217
218 - when having the focus the top level window gets activated/deactivated
219 - ???
220 */
221
222 if ( m_data->fbo )
223 {
224 if ( m_data->fbo->size() != fboSize )
225 {
226 delete m_data->fbo;
227 m_data->fbo = NULL;
228 }
229 }
230
231 if ( m_data->fbo == NULL )
232 {
233 QOpenGLFramebufferObjectFormat fboFormat;
234 fboFormat.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
235
236 if ( m_data->numFBOSamples > 0 )
237 fboFormat.setSamples( m_data->numFBOSamples );
238
239 m_data->fbo = new QOpenGLFramebufferObject( fboSize, fboFormat );
240 m_data->fboDirty = true;
241 }
242
243 if ( m_data->fboDirty )
244 {
245 m_data->fbo->bind();
246
247 QOpenGLPaintDevice pd( fboSize );
248
249 QPainter fboPainter( &pd );
250 fboPainter.scale( pixelRatio, pixelRatio );
251 draw( &fboPainter);
252 fboPainter.end();
253
254 m_data->fboDirty = false;
255 }
256
257 QOpenGLFramebufferObject::blitFramebuffer( NULL, m_data->fbo );
258 }
259 else
260 {
261 painter.begin( this );
262 draw( &painter );
263 }
264
265 if ( hasFocusIndicator )
266 drawFocusIndicator( &painter );
267}
268
271{
272 // nothing to do
273}
274
275#include "moc_qwt_plot_opengl_canvas.cpp"
static qreal devicePixelRatio(const QPaintDevice *)
FocusIndicator focusIndicator() const
QPainterPath canvasBorderPath(const QRect &rect) const
virtual void drawFocusIndicator(QPainter *)
Base class of QwtPlotOpenGLCanvas and QwtPlotGLCanvas.
bool testPaintAttribute(PaintAttribute) const
@ BackingStore
Paint double buffered reusing the content of the pixmap buffer when possible.
void draw(QPainter *)
Helper function for the derived plot canvas.
A 2-D plotting widget.
Definition qwt_plot.h:79
virtual void paintEvent(QPaintEvent *) override
virtual void initializeGL() override
No operation - reserved for some potential use in the future.
virtual ~QwtPlotOpenGLCanvas()
Destructor.
Q_INVOKABLE QPainterPath borderPath(const QRect &) const
QwtPlotOpenGLCanvas(QwtPlot *=NULL)
Constructor.
virtual void paintGL() override
Paint the plot.
virtual void resizeGL(int width, int height) override
No operation - reserved for some potential use in the future.
virtual bool event(QEvent *) override
virtual Q_INVOKABLE void invalidateBackingStore() override
Invalidate the internal backing store.