Skip to content

Commit

Permalink
[Rendering] Only render in preview jobs layers that are fast enough
Browse files Browse the repository at this point in the history
This implements the improvements discussed in the mailing list thread
https://lists.osgeo.org/pipermail/qgis-developer/2017-November/050524.html
to avoid rendering layers in preview jobs that take too much time to render.
  • Loading branch information
rouault authored and nyalldawson committed Dec 4, 2017
1 parent 32ba5bf commit 997619c
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 2 deletions.
2 changes: 2 additions & 0 deletions python/core/qgis.sip
Expand Up @@ -241,6 +241,8 @@ const double DEFAULT_LINE_WIDTH;
const double DEFAULT_SEGMENT_EPSILON;




typedef unsigned long long qgssize;


Expand Down
1 change: 1 addition & 0 deletions python/core/qgsmaplayer.sip
Expand Up @@ -916,6 +916,7 @@ Time stamp of data source in the moment when data/metadata were loaded by provid
:rtype: bool
%End


public slots:

void setMinimumScale( double scale );
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgis.h
Expand Up @@ -440,6 +440,18 @@ const double DEFAULT_LINE_WIDTH = 0.26;
//! Default snapping tolerance for segments
const double DEFAULT_SEGMENT_EPSILON = 1e-8;

///@cond PRIVATE
#ifndef SIP_RUN

//! Delay between the scheduling of 2 preview jobs
const int PREVIEW_JOB_DELAY_MS = 250;

//! Maximum rendering time for a layer of a preview job
const int MAXIMUM_LAYER_PREVIEW_TIME_MS = 250;
#endif

///@endcond

typedef QMap<QString, QString> QgsStringMap SIP_SKIP;

/**
Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsdataprovider.cpp
Expand Up @@ -42,3 +42,7 @@ void QgsDataProvider::setListening( bool isListening )
Q_UNUSED( isListening );
}

bool QgsDataProvider::renderInPreview( double lastRenderingTimeMS, double maxRenderingTimeMS )
{
return lastRenderingTimeMS <= maxRenderingTimeMS;
}
15 changes: 15 additions & 0 deletions src/core/qgsdataprovider.h
Expand Up @@ -461,6 +461,21 @@ class CORE_EXPORT QgsDataProvider : public QObject
*/
virtual void setListening( bool isListening );

/**
* Returns whether the layer must be rendered in preview jobs.
*
* The base implementation returns lastRenderingTimeMS <= maxRenderingTimeMS
*
* \param lastRenderingTimeMS last rendering time in milliseconds.
* \param maxRenderingTimeMS maximum allowed rendering time in milliseconds.
* \returns true if the layer must be rendered.
*
* \since QGIS 3.0
*
* \note not available in Python bindings
*/
virtual bool renderInPreview( double lastRenderingTimeMS, double maxRenderingTimeMS ); // SIP_SKIP

signals:

/**
Expand Down
20 changes: 20 additions & 0 deletions src/core/qgsmaplayer.h
Expand Up @@ -882,6 +882,25 @@ class CORE_EXPORT QgsMapLayer : public QObject
*/
bool isRefreshOnNotifyEnabled() const { return mIsRefreshOnNofifyEnabled; }

///@cond PRIVATE
#ifndef SIP_RUN

/**
* Set last rendering time.
*
* \note not available in Python bindings
*/
void setLastRenderingTime( double time ) { mLastRenderingTime = time; }

/**
* Get last rendering time.
*
* \note not available in Python bindings
*/
double lastRenderingTime() const { return mLastRenderingTime; }
#endif
///@endcond

public slots:

/**
Expand Down Expand Up @@ -1221,6 +1240,7 @@ class CORE_EXPORT QgsMapLayer : public QObject
//! Renderer for 3D views
QgsAbstract3DRenderer *m3DRenderer = nullptr;

double mLastRenderingTime = 0.0;
};

Q_DECLARE_METATYPE( QgsMapLayer * )
Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsmaprenderercustompainterjob.cpp
Expand Up @@ -265,6 +265,10 @@ void QgsMapRendererCustomPainterJob::doRender()
job.renderer->render();

job.renderingTime = layerTime.elapsed();
if ( job.layer )
{
job.layer->setLastRenderingTime( job.renderingTime );
}
}

if ( job.img )
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsmaprendererjob.cpp
Expand Up @@ -242,6 +242,13 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter *painter, QgsLabelingEn
continue;
}

if ( ( mSettings.flags() & QgsMapSettings::RenderPreviewJob ) &&
!ml->dataProvider()->renderInPreview( ml->lastRenderingTime(), MAXIMUM_LAYER_PREVIEW_TIME_MS ) )
{
QgsDebugMsgLevel( "Layer not rendered because it does not match the renderInPreview criterion", 3 );
continue;
}

QgsRectangle r1 = mSettings.visibleExtent(), r2;
QgsCoordinateTransform ct;

Expand Down
4 changes: 4 additions & 0 deletions src/core/qgsmaprendererparalleljob.cpp
Expand Up @@ -270,6 +270,10 @@ void QgsMapRendererParallelJob::renderLayerStatic( LayerRenderJob &job )
QgsDebugMsg( "Caught unhandled unknown exception" );
}
job.renderingTime = t.elapsed();
if ( job.layer )
{
job.layer->setLastRenderingTime( job.renderingTime );
}
QgsDebugMsgLevel( QString( "job %1 end [%2 ms] (layer %3)" ).arg( reinterpret_cast< quint64 >( &job ), 0, 16 ).arg( job.renderingTime ).arg( job.layer ? job.layer->id() : QString() ), 2 );
}

Expand Down
3 changes: 1 addition & 2 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -66,7 +66,6 @@ email : sherman at mrcc.com
#include "qgsmapthemecollection.h"
#include <cmath>


/**
* \ingroup gui
* Deprecated to be deleted, stuff from here should be moved elsewhere.
Expand Down Expand Up @@ -2299,7 +2298,7 @@ void QgsMapCanvas::stopPreviewJobs()
void QgsMapCanvas::schedulePreviewJob( int number )
{
mPreviewTimer.setSingleShot( true );
mPreviewTimer.setInterval( 250 );
mPreviewTimer.setInterval( PREVIEW_JOB_DELAY_MS );
disconnect( mPreviewTimerConnection );
mPreviewTimerConnection = connect( &mPreviewTimer, &QTimer::timeout, this, [ = ]()
{
Expand Down

0 comments on commit 997619c

Please sign in to comment.