metadata
Wenzel Jakob 2011-10-27 12:57:53 -04:00
commit 3562fffa40
3 changed files with 57 additions and 10 deletions

View File

@ -74,12 +74,15 @@ bool ConditionVariable::wait(int ms) {
struct timespec ts;
ts.tv_sec = tv.tv_sec + ms/1000;
ts.tv_nsec = (tv.tv_usec + ms % 1000) * 1000;
ts.tv_nsec = tv.tv_usec * 1000 + (ms % 1000) * 1000000;
if (ts.tv_nsec >= 1000000000) {
ts.tv_nsec -= 1000000000;
ts.tv_sec++;
}
int retval = pthread_cond_timedwait(&m_cond, &m_mutex->m_mutex, &ts);
#if defined(WIN32)
/* Should be outside of the switch statement (depending
on the used compiler, the constants ETIMEDOUT and WSAETIMEDOUT
on the used environment, the constants ETIMEDOUT and WSAETIMEDOUT
are potentially identical */
if (retval == WSAETIMEDOUT)
return false;

View File

@ -163,12 +163,11 @@ MainWindow::MainWindow(QWidget *parent) :
connect(m_renderListener, SIGNAL(jobFinished(const RenderJob *, bool)),
this, SLOT(onJobFinished(const RenderJob *, bool)), Qt::QueuedConnection);
connect(m_renderListener, SIGNAL(refresh(const RenderJob *, const Bitmap *)),
this, SLOT(onRefresh(const RenderJob *, const Bitmap *)), Qt::BlockingQueuedConnection);
connect(m_renderListener, SIGNAL(workEnd(const RenderJob *, const ImageBlock *)),
this, SLOT(onWorkEnd(const RenderJob *, const ImageBlock *)), Qt::DirectConnection);
connect(m_renderListener, SIGNAL(workBegin(const RenderJob *, const RectangularWorkUnit *, int)),
this, SLOT(onWorkBegin(const RenderJob *, const RectangularWorkUnit *, int)), Qt::DirectConnection);
connect(m_renderListener, SIGNAL(refresh()), this, SLOT(onRefresh()), Qt::QueuedConnection);
connect(m_consoleAppender,
SIGNAL(progressMessage(const RenderJob *, const QString &, float, const QString &)),
this, SLOT(onProgressMessage(const RenderJob *, const QString &, float, const QString &)),
@ -1513,7 +1512,7 @@ void MainWindow::onJobFinished(const RenderJob *job, bool cancelled) {
ui->glView->resumePreview();
}
}
onRefresh(job, NULL);
refresh(job, NULL);
context->renderJob = NULL;
updateUI();
if (ui->tabBar->currentIndex() != -1 &&
@ -1673,10 +1672,18 @@ void MainWindow::onWorkEnd(const RenderJob *job, const ImageBlock *block) {
emit updateView();
}
void MainWindow::onRefresh(const RenderJob *job, const Bitmap *_bitmap) {
void MainWindow::onRefresh() {
const QRenderListener::RefreshRequest *req = m_renderListener->acquireRefreshRequest();
if (req)
refresh(req->first, req->second);
m_renderListener->releaseRefreshRequest();
}
void MainWindow::refresh(const RenderJob *job, const Bitmap *_bitmap) {
SceneContext *context = getContext(job, false);
if (context == NULL)
return;
Film *film = context->scene->getFilm();
Point2i co = film->getCropOffset();
Bitmap *bitmap = context->framebuffer;

View File

@ -25,6 +25,10 @@
#define MAX_RECENT_FILES 10
// amount of time that a rendering thread will wait for the GUI to accept a
// render view refresh request to show intermediate progress (in ms)
#define REFRESH_TIMEOUT 50
namespace Ui {
class MainWindow;
}
@ -41,6 +45,14 @@ class PreviewSettingsDlg;
class QRenderListener : public QObject, public RenderListener {
Q_OBJECT
public:
typedef std::pair<const RenderJob *, const Bitmap *> RefreshRequest;
QRenderListener() {
m_mutex = new Mutex();
m_cond = new ConditionVariable(m_mutex);
m_refreshRequest = NULL;
}
/// Called when work has begun in a rectangular image region
inline void workBeginEvent(const RenderJob *job, const RectangularWorkUnit *wu, int worker) {
emit workBegin(job, wu, worker);
@ -50,10 +62,25 @@ public:
inline void workEndEvent(const RenderJob *job, const ImageBlock *wr) {
emit workEnd(job, wr);
}
/// Called when the whole target image has been altered in some way
inline void refreshEvent(const RenderJob *job, const Bitmap *bitmap) {
emit refresh(job, bitmap);
m_mutex->lock();
RefreshRequest request = std::make_pair(job, bitmap);
/* Potentially overwrite a previous refresh request */
m_refreshRequest = &request;
/* Asynchronously signal the GUI */
emit refresh();
/* Wait for the GUI to draw the image (or another
thread to overwrite the refresh request) */
m_cond->wait(REFRESH_TIMEOUT);
m_refreshRequest = NULL;
m_mutex->unlock();
}
/// Called when a render job has completed successfully or unsuccessfully
@ -61,14 +88,23 @@ public:
emit jobFinished(job, cancelled);
}
inline const RefreshRequest *acquireRefreshRequest() { m_mutex->lock(); return m_refreshRequest; }
inline void releaseRefreshRequest() { m_refreshRequest = NULL; m_cond->signal(); m_mutex->unlock(); }
MTS_DECLARE_CLASS()
signals:
void workBegin(const RenderJob *job, const RectangularWorkUnit *wu, int worker);
void workEnd(const RenderJob *job, const ImageBlock *wr);
void refresh(const RenderJob *job, const Bitmap *bitmap);
void jobFinished(const RenderJob *job, bool cancelled);
void refresh();
protected:
virtual ~QRenderListener() { }
private:
ref<Mutex> m_mutex;
ref<ConditionVariable> m_cond;
RefreshRequest *m_refreshRequest;
};
class PreviewSettingsDialog;
@ -97,6 +133,7 @@ protected:
void drawVisualWorkUnit(SceneContext *context, const VisualWorkUnit &block);
void checkForUpdates(bool notifyIfNone = false);
void saveAs(SceneContext *ctx, const QString &targetFile);
void refresh(const RenderJob *job, const Bitmap *bitmap);
QSize sizeHint() const;
signals:
@ -137,7 +174,7 @@ private slots:
void onClearRecent();
void onWorkBegin(const RenderJob *job, const RectangularWorkUnit *wu, int worker);
void onWorkEnd(const RenderJob *job, const ImageBlock *wr);
void onRefresh(const RenderJob *job, const Bitmap *bitmap);
void onRefresh();
void onJobFinished(const RenderJob *job, bool cancelled);
void onProgressMessage(const RenderJob *job, const QString &name,
float progress, const QString &eta);