From d4f2ff4e1d4bb13e44b9c31211633120993edc0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Lemaire?= Date: Sun, 29 Apr 2012 20:42:36 +0000 Subject: [PATCH] paysages: Threaded previews. git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@311 b1fd45b6-86a6-48da-8261-f70d1f35bdcc --- TODO | 5 +++ gui_qt/basepreview.cpp | 69 ++++++++++++++++++++++++++---------------- gui_qt/basepreview.h | 8 +++-- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index 567232b..012935b 100644 --- a/TODO +++ b/TODO @@ -11,12 +11,17 @@ Technology Preview 2 : - Improve curve editor. - Water and terrain LOD moves with the camera, fix it like in the wanderer. - There should not have to be more preview threads than core. +- Handle preview threads termination. +- Add preview threads pausing (for rendering). +- Add preview chunks priority (for visible previews). +- Interrupt preview chunk renderings that will be discarded at commit. Technology Preview 3 : - Restore render progress. - Add antialiasing option (pay attention to memory usage). - Add basic vegetation system (not sure). - Improve sky rendering (colors and light halo). +- Add a progress indicator on previews. Release Candidate : - Polish all features and UI. diff --git a/gui_qt/basepreview.cpp b/gui_qt/basepreview.cpp index a122621..c3009b4 100644 --- a/gui_qt/basepreview.cpp +++ b/gui_qt/basepreview.cpp @@ -6,15 +6,14 @@ #include #include +/*************** PreviewChunk ***************/ class PreviewChunk { public: - PreviewChunk(BasePreview* preview, QImage* pixbuf, QMutex* lock, int xstart, int ystart, int xsize, int ysize) + PreviewChunk(BasePreview* preview, int xstart, int ystart, int xsize, int ysize) { _preview = preview; - _pixbuf = pixbuf; - _lock = lock; _xstart = xstart; _ystart = ystart; _xsize = xsize; @@ -36,26 +35,25 @@ public: bool render() { bool changed = false; + int revision; if (_need_render) { _need_render = false; - _lock->lock(); - QImage tempbuffer = _pixbuf->copy(_xstart, _ystart, _xsize, _ysize); - _lock->unlock(); + QImage pixbuf = _preview->startChunkTransaction(_xstart, _ystart, _xsize, _ysize, &revision); for (int x = 0; x < _xsize; x++) { for (int y = 0; y < _ysize; y++) { - QRgb col = tempbuffer.pixel(x, y); + QRgb col = pixbuf.pixel(x, y); if (qAlpha(col) < 255) { QColor newcol = _preview->getPixelColor(_xstart + x, _ystart + y); newcol.setAlpha(255); - tempbuffer.setPixel(x, y, newcol.rgb()); + pixbuf.setPixel(x, y, newcol.rgb()); changed = true; } @@ -64,16 +62,7 @@ public: if (changed) { - _lock->lock(); - for (int x = 0; x < _xsize; x++) - { - for (int y = 0; y < _ysize; y++) - { - _pixbuf->setPixel(_xstart + x, _ystart + y, tempbuffer.pixel(x, y)); - } - } - _lock->unlock(); - _preview->tellContentChange(); + _preview->commitChunkTransaction(&pixbuf, _xstart, _ystart, _xsize, _ysize, revision); } } @@ -81,8 +70,6 @@ public: } private: BasePreview* _preview; - QImage* _pixbuf; - QMutex* _lock; bool _need_render; int _xstart; int _ystart; @@ -230,6 +217,7 @@ QWidget(parent) this->pixbuf->fill(0x00000000); _width = width(); _height = height(); + _revision = 0; this->alive = true; @@ -311,6 +299,29 @@ void BasePreview::redraw() emit(redrawRequested()); } +QImage BasePreview::startChunkTransaction(int x, int y, int w, int h, int* revision) +{ + *revision = _revision; + return pixbuf->copy(x, y, w, h); +} + +void BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision) +{ + if (revision == _revision) + { + lock_drawing->lock(); + for (int ix = 0; ix < w; ix++) + { + for (int iy = 0; iy < h; iy++) + { + pixbuf->setPixel(x + ix, y + iy, chunk->pixel(ix, iy)); + } + } + lock_drawing->unlock(); + emit contentChange(); + } +} + QColor BasePreview::getPixelColor(int x, int y) { return getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset); @@ -328,7 +339,7 @@ void BasePreview::handleRedraw() painter.setOpacity(0.99); painter.drawImage(0, 0, part); - _drawing_manager->updateChunks(this); + updateChunks(); lock_drawing->unlock(); } @@ -353,7 +364,7 @@ void BasePreview::resizeEvent(QResizeEvent* event) { for (int y = 0; y < _height; y += 32) { - _drawing_manager->addChunk(new PreviewChunk(this, pixbuf, lock_drawing, x, y, x + 32 > _width ? _width - x : 32, y + 32 > _height ? _height - y : 32)); + _drawing_manager->addChunk(new PreviewChunk(this, x, y, x + 32 > _width ? _width - x : 32, y + 32 > _height ? _height - y : 32)); } } @@ -380,6 +391,12 @@ void BasePreview::updateScaling() } } +void BasePreview::updateChunks() +{ + _drawing_manager->updateChunks(this); + _revision++; +} + void BasePreview::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) @@ -430,7 +447,7 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event) lock_drawing->lock(); pixbuf->fill(0x00000000); - _drawing_manager->updateChunks(this); + updateChunks(); lock_drawing->unlock(); } else @@ -468,7 +485,7 @@ void BasePreview::mouseMoveEvent(QMouseEvent* event) pixbuf->fill(0x00000000); painter.drawImage(xstart + ndx, ystart + ndy, part); - _drawing_manager->updateChunks(this); + updateChunks(); lock_drawing->unlock(); emit contentChange(); @@ -546,7 +563,7 @@ void BasePreview::wheelEvent(QWheelEvent* event) pixbuf->fill(0x00000000); painter.setOpacity(0.99); painter.drawImage(0, 0, part); - _drawing_manager->updateChunks(this); + updateChunks(); lock_drawing->unlock(); emit contentChange(); @@ -559,7 +576,7 @@ void BasePreview::wheelEvent(QWheelEvent* event) pixbuf->fill(0x00000000); painter.setOpacity(0.99); painter.drawImage((width - part.width()) / 2, (height - part.height()) / 2, part); - _drawing_manager->updateChunks(this); + updateChunks(); lock_drawing->unlock(); emit contentChange(); diff --git a/gui_qt/basepreview.h b/gui_qt/basepreview.h index a74260c..844a1bd 100644 --- a/gui_qt/basepreview.h +++ b/gui_qt/basepreview.h @@ -17,10 +17,11 @@ public: static void initDrawers(); static void stopDrawers(); - + void redraw(); - inline void tellContentChange() {emit contentChange();} + QImage startChunkTransaction(int x, int y, int w, int h, int* revision); + void commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision); QColor getPixelColor(int x, int y); @@ -37,6 +38,7 @@ protected: private: void updateScaling(); + void updateChunks(); void resizeEvent(QResizeEvent* event); void paintEvent(QPaintEvent* event); @@ -50,6 +52,8 @@ private: int _width; int _height; + + int _revision; int mousex; int mousey;