qwt_plot_opengl_canvas.cpp
/******************************************************************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#include "qwt_plot_opengl_canvas.h"
#include "qwt_plot.h"
#include "qwt_painter.h"
#include <qpainter.h>
#include <qpainterpath.h>
#include <qcoreevent.h>
#include <qopenglframebufferobject.h>
#include <qopenglpaintdevice.h>
class QwtPlotOpenGLCanvas::PrivateData
{
public:
PrivateData()
: isPolished( false )
, fboDirty( true )
, fbo( NULL )
{
}
~PrivateData()
{
delete fbo;
}
int numSamples;
bool isPolished;
bool fboDirty;
QOpenGLFramebufferObject* fbo;
};
QwtPlotOpenGLCanvas::QwtPlotOpenGLCanvas( QwtPlot* plot )
: QOpenGLWidget( plot )
, QwtPlotAbstractGLCanvas( this )
{
QSurfaceFormat fmt = format();
fmt.setSamples( 4 );
init( fmt );
}
QwtPlotOpenGLCanvas::QwtPlotOpenGLCanvas(
const QSurfaceFormat& format, QwtPlot* plot )
: QOpenGLWidget( plot )
, QwtPlotAbstractGLCanvas( this )
{
init( format );
}
void QwtPlotOpenGLCanvas::init( const QSurfaceFormat& format )
{
m_data = new PrivateData;
m_data->numSamples = format.samples();
setFormat( format );
#if 1
setAttribute( Qt::WA_OpaquePaintEvent, true );
#endif
setLineWidth( 2 );
setFrameShadow( QFrame::Sunken );
setFrameShape( QFrame::Panel );
}
QwtPlotOpenGLCanvas::~QwtPlotOpenGLCanvas()
{
delete m_data;
}
void QwtPlotOpenGLCanvas::paintEvent( QPaintEvent* event )
{
if ( m_data->isPolished )
QOpenGLWidget::paintEvent( event );
}
bool QwtPlotOpenGLCanvas::event( QEvent* event )
{
const bool ok = QOpenGLWidget::event( event );
if ( event->type() == QEvent::PolishRequest )
{
// In opposite to non OpenGL widgets receive pointless
// early repaints. As we always have a QEvent::PolishRequest
// followed by QEvent::Paint, we can ignore all these repaints.
m_data->isPolished = true;
}
if ( event->type() == QEvent::PolishRequest ||
event->type() == QEvent::StyleChange )
{
// assuming, that we always have a styled background
// when we have a style sheet
setAttribute( Qt::WA_StyledBackground,
testAttribute( Qt::WA_StyleSheet ) );
}
return ok;
}
void QwtPlotOpenGLCanvas::replot()
{
QwtPlotAbstractGLCanvas::replot();
}
void QwtPlotOpenGLCanvas::invalidateBackingStore()
{
m_data->fboDirty = true;
}
void QwtPlotOpenGLCanvas::clearBackingStore()
{
delete m_data->fbo;
m_data->fbo = NULL;
}
QPainterPath QwtPlotOpenGLCanvas::borderPath( const QRect& rect ) const
{
return canvasBorderPath( rect );
}
void QwtPlotOpenGLCanvas::initializeGL()
{
}
void QwtPlotOpenGLCanvas::paintGL()
{
const bool hasFocusIndicator =
hasFocus() && focusIndicator() == CanvasFocusIndicator;
QPainter painter;
if ( testPaintAttribute( QwtPlotOpenGLCanvas::BackingStore ) &&
QOpenGLFramebufferObject::hasOpenGLFramebufferBlit() )
{
const qreal pixelRatio = QwtPainter::devicePixelRatio( NULL );
const QSize fboSize = size() * pixelRatio;
if ( hasFocusIndicator )
painter.begin( this );
/*
QOpenGLWidget has its own internal FBO, that is used to restore
its content without having to repaint. This works fine when f.e
a rubberband is moving on top, but there are still situations,
where we can repaint without an potentially expensive replot:
- when having the focus the top level window gets activated/deactivated
- ???
*/
if ( m_data->fbo )
{
if ( m_data->fbo->size() != fboSize )
{
delete m_data->fbo;
m_data->fbo = NULL;
}
}
if ( m_data->fbo == NULL )
{
QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setSamples( m_data->numSamples );
fboFormat.setAttachment( QOpenGLFramebufferObject::CombinedDepthStencil );
m_data->fbo = new QOpenGLFramebufferObject( fboSize, fboFormat );
m_data->fboDirty = true;
}
if ( m_data->fboDirty )
{
m_data->fbo->bind();
QOpenGLPaintDevice pd( fboSize );
QPainter fboPainter( &pd );
fboPainter.scale( pixelRatio, pixelRatio );
draw( &fboPainter);
fboPainter.end();
m_data->fboDirty = false;
}
QOpenGLFramebufferObject::blitFramebuffer( NULL, m_data->fbo );
}
else
{
painter.begin( this );
draw( &painter );
}
if ( hasFocusIndicator )
drawFocusIndicator( &painter );
}
void QwtPlotOpenGLCanvas::resizeGL( int, int )
{
// nothing to do
}
#if QWT_MOC_INCLUDE
#include "moc_qwt_plot_opengl_canvas.cpp"
#endif
QwtPainter::devicePixelRatio
static qreal devicePixelRatio(const QPaintDevice *)
Definition: qwt_painter.cpp:1491
QwtPlotAbstractCanvas::focusIndicator
FocusIndicator focusIndicator() const
Definition: qwt_plot_abstract_canvas.cpp:578
QwtPlotAbstractCanvas::canvasBorderPath
QPainterPath canvasBorderPath(const QRect &rect) const
Definition: qwt_plot_abstract_canvas.cpp:619
QwtPlotAbstractCanvas::drawFocusIndicator
virtual void drawFocusIndicator(QPainter *)
Definition: qwt_plot_abstract_canvas.cpp:587
QwtPlotAbstractCanvas::CanvasFocusIndicator
@ CanvasFocusIndicator
Definition: qwt_plot_abstract_canvas.h:39
QwtPlotAbstractGLCanvas
Base class of QwtPlotOpenGLCanvas and QwtPlotGLCanvas.
Definition: qwt_plot_abstract_canvas.h:88
QwtPlotAbstractGLCanvas::testPaintAttribute
bool testPaintAttribute(PaintAttribute) const
Definition: qwt_plot_abstract_canvas.cpp:952
QwtPlotAbstractGLCanvas::setLineWidth
void setLineWidth(int)
Definition: qwt_plot_abstract_canvas.cpp:1033
QwtPlotAbstractGLCanvas::BackingStore
@ BackingStore
Paint double buffered reusing the content of the pixmap buffer when possible.
Definition: qwt_plot_abstract_canvas.h:110
QwtPlotAbstractGLCanvas::setFrameShape
void setFrameShape(QFrame::Shape)
Definition: qwt_plot_abstract_canvas.cpp:1011
QwtPlotAbstractGLCanvas::replot
void replot()
Definition: qwt_plot_abstract_canvas.cpp:1093
QwtPlotAbstractGLCanvas::setFrameShadow
void setFrameShadow(QFrame::Shadow)
Definition: qwt_plot_abstract_canvas.cpp:991
QwtPlotAbstractGLCanvas::draw
void draw(QPainter *)
Helper function for the derived plot canvas.
Definition: qwt_plot_abstract_canvas.cpp:1112
QwtPlot
A 2-D plotting widget.
Definition: qwt_plot.h:79
QwtPlotOpenGLCanvas::paintEvent
virtual void paintEvent(QPaintEvent *) override
Definition: qwt_plot_opengl_canvas.cpp:101
QwtPlotOpenGLCanvas::initializeGL
virtual void initializeGL() override
No operation - reserved for some potential use in the future.
Definition: qwt_plot_opengl_canvas.cpp:174
QwtPlotOpenGLCanvas::~QwtPlotOpenGLCanvas
virtual ~QwtPlotOpenGLCanvas()
Destructor.
Definition: qwt_plot_opengl_canvas.cpp:90
QwtPlotOpenGLCanvas::borderPath
Q_INVOKABLE QPainterPath borderPath(const QRect &) const
Definition: qwt_plot_opengl_canvas.cpp:168
QwtPlotOpenGLCanvas::replot
void replot()
Definition: qwt_plot_opengl_canvas.cpp:142
QwtPlotOpenGLCanvas::QwtPlotOpenGLCanvas
QwtPlotOpenGLCanvas(QwtPlot *=NULL)
Constructor.
Definition: qwt_plot_opengl_canvas.cpp:48
QwtPlotOpenGLCanvas::paintGL
virtual void paintGL() override
Paint the plot.
Definition: qwt_plot_opengl_canvas.cpp:179
QwtPlotOpenGLCanvas::resizeGL
virtual void resizeGL(int width, int height) override
No operation - reserved for some potential use in the future.
Definition: qwt_plot_opengl_canvas.cpp:251
QwtPlotOpenGLCanvas::event
virtual bool event(QEvent *) override
Definition: qwt_plot_opengl_canvas.cpp:112
QwtPlotOpenGLCanvas::invalidateBackingStore
virtual Q_INVOKABLE void invalidateBackingStore() override
Invalidate the internal backing store.
Definition: qwt_plot_opengl_canvas.cpp:148