paysages : Fixed previews possible segfaults by not changing data while chunks are processing them.

git-svn-id: https://subversion.assembla.com/svn/thunderk/paysages@397 b1fd45b6-86a6-48da-8261-f70d1f35bdcc
This commit is contained in:
Michaël Lemaire 2012-07-23 16:56:24 +00:00 committed by ThunderK
parent 3ad79c9b7c
commit fe561c2062
7 changed files with 80 additions and 18 deletions

3
TODO
View file

@ -22,9 +22,6 @@ Technology Preview 2 :
=> Add curve modes => Add curve modes
=> Add logarithmic mode => Add logarithmic mode
=> Add zoom and scrolling => Add zoom and scrolling
- Fix "RGB parameters out of range" (and segfault) on some previews, caused by data changing during a chunk computation.
=> May need to change the updateData system.
=> Previews need to be paused while updating data.
- Lock some previews together (eg: terrain height and colored preview). - Lock some previews together (eg: terrain height and colored preview).
- Find a new licence. - Find a new licence.

View file

@ -93,6 +93,10 @@ public:
{ {
_preview->commitChunkTransaction(&pixbuf, _xstart, _ystart, _xsize, _ysize, revision); _preview->commitChunkTransaction(&pixbuf, _xstart, _ystart, _xsize, _ysize, revision);
} }
else
{
_preview->rollbackChunkTransaction();
}
} }
return changed; return changed;
@ -194,6 +198,23 @@ void PreviewDrawingManager::removeChunks(BasePreview* preview)
logDebug(QString("[Previews] %1 chunks removed, %2 remaining").arg(removed).arg(_chunks.size())); logDebug(QString("[Previews] %1 chunks removed, %2 remaining").arg(removed).arg(_chunks.size()));
} }
void PreviewDrawingManager::suspendChunks(BasePreview* preview)
{
_lock.lock();
for (int i = 0; i < _updateQueue.size(); i++)
{
PreviewChunk* chunk;
chunk = _updateQueue.at(i);
if (chunk->isFrom(preview))
{
_updateQueue.takeAt(i);
i--;
}
}
// TODO Interrupt currently processing chunks
_lock.unlock();
}
void PreviewDrawingManager::updateChunks(BasePreview* preview) void PreviewDrawingManager::updateChunks(BasePreview* preview)
{ {
for (int i = 0; i < _chunks.size(); i++) for (int i = 0; i < _chunks.size(); i++)
@ -293,6 +314,8 @@ QWidget(parent)
_width = width(); _width = width();
_height = height(); _height = height();
_revision = 0; _revision = 0;
_transactions_count = 0;
_redraw_requested = false;
_info = new QLabel(this); _info = new QLabel(this);
_info->setVisible(false); _info->setVisible(false);
@ -301,11 +324,12 @@ QWidget(parent)
this->alive = true; this->alive = true;
QObject::connect(this, SIGNAL(contentChange()), this, SLOT(update())); QObject::connect(this, SIGNAL(contentChange()), this, SLOT(update()));
QObject::connect(this, SIGNAL(redrawRequested()), this, SLOT(handleRedraw()));
this->setMinimumSize(256, 256); this->setMinimumSize(256, 256);
this->setMaximumSize(256, 256); this->setMaximumSize(256, 256);
this->resize(256, 256); this->resize(256, 256);
startTimer(50);
} }
BasePreview::~BasePreview() BasePreview::~BasePreview()
@ -440,18 +464,31 @@ void BasePreview::toggleChangeEvent(QString, bool)
void BasePreview::redraw() void BasePreview::redraw()
{ {
emit(redrawRequested()); _drawing_manager->suspendChunks(this);
_redraw_requested = true;
} }
QImage BasePreview::startChunkTransaction(int x, int y, int w, int h, int* revision) QImage BasePreview::startChunkTransaction(int x, int y, int w, int h, int* revision)
{ {
QImage result;
_lock_drawing->lock();
*revision = _revision; *revision = _revision;
return _pixbuf->copy(x, y, w, h); result = _pixbuf->copy(x, y, w, h);
_transactions_count++;
_lock_drawing->unlock();
return result;
} }
void BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision) bool BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision)
{ {
bool result;
_lock_drawing->lock(); _lock_drawing->lock();
if (revision == _revision) if (revision == _revision)
{ {
for (int ix = 0; ix < w; ix++) for (int ix = 0; ix < w; ix++)
@ -462,7 +499,26 @@ void BasePreview::commitChunkTransaction(QImage* chunk, int x, int y, int w, int
} }
} }
emit contentChange(); emit contentChange();
result = true;
} }
else
{
result = false;
}
_transactions_count--;
_lock_drawing->unlock();
return result;
}
void BasePreview::rollbackChunkTransaction()
{
_lock_drawing->lock();
_transactions_count--;
_lock_drawing->unlock(); _lock_drawing->unlock();
} }
@ -471,12 +527,16 @@ QColor BasePreview::getPixelColor(int x, int y)
return getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset); return getColor((double) (x - _width / 2) * scaling + xoffset, (double) (y - _height / 2) * scaling + yoffset);
} }
void BasePreview::handleRedraw() void BasePreview::timerEvent(QTimerEvent*)
{ {
_lock_drawing->lock(); _lock_drawing->lock();
if (_redraw_requested && _transactions_count == 0)
{
updateData(); updateData();
invalidatePixbuf(128); invalidatePixbuf(128);
_redraw_requested = false;
}
_lock_drawing->unlock(); _lock_drawing->unlock();
} }

View file

@ -44,7 +44,8 @@ public:
void redraw(); void redraw();
QImage startChunkTransaction(int x, int y, int w, int h, int* revision); 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); bool commitChunkTransaction(QImage* chunk, int x, int y, int w, int h, int revision);
void rollbackChunkTransaction();
QColor getPixelColor(int x, int y); QColor getPixelColor(int x, int y);
@ -72,6 +73,7 @@ private:
void updateChunks(); void updateChunks();
void invalidatePixbuf(int value); void invalidatePixbuf(int value);
void timerEvent(QTimerEvent* event);
void showEvent(QShowEvent* event); void showEvent(QShowEvent* event);
void resizeEvent(QResizeEvent* event); void resizeEvent(QResizeEvent* event);
void paintEvent(QPaintEvent* event); void paintEvent(QPaintEvent* event);
@ -94,6 +96,8 @@ private:
int _height; int _height;
int _revision; int _revision;
int _transactions_count;
bool _redraw_requested;
int mousex; int mousex;
int mousey; int mousey;
@ -120,7 +124,6 @@ signals:
void redrawRequested(); void redrawRequested();
private slots: private slots:
void handleRedraw();
void choiceSelected(QAction* action); void choiceSelected(QAction* action);
}; };
@ -153,6 +156,7 @@ public:
void addChunk(PreviewChunk* chunk); void addChunk(PreviewChunk* chunk);
void removeChunks(BasePreview* preview); void removeChunks(BasePreview* preview);
void updateChunks(BasePreview* preview); void updateChunks(BasePreview* preview);
void suspendChunks(BasePreview* preview);
void updateAllChunks(); void updateAllChunks();
void performOneThreadJob(); void performOneThreadJob();
int chunkCount(); int chunkCount();

View file

@ -2,6 +2,7 @@
#include <math.h> #include <math.h>
#if 0
static Vector3 _betaR = {5.5e-6, 13.0e-6, 22.4e-6}; /* Rayleigh scattering coefficients at sea level */ static Vector3 _betaR = {5.5e-6, 13.0e-6, 22.4e-6}; /* Rayleigh scattering coefficients at sea level */
static Vector3 _betaM = {21e-6, 0.0, 0.0}; /* Mie scattering coefficients at sea level */ static Vector3 _betaM = {21e-6, 0.0, 0.0}; /* Mie scattering coefficients at sea level */
static double _Hr = 7994; /* Rayleigh scale height */ static double _Hr = 7994; /* Rayleigh scale height */
@ -10,6 +11,7 @@ static double _radiusEarth = 6360e3; /* Earth radius */
static double _radiusAtmosphere = 6420e3; /* Atmosphere radius */ static double _radiusAtmosphere = 6420e3; /* Atmosphere radius */
static double _sunIntensity = 20.0; /* Sun intensity */ static double _sunIntensity = 20.0; /* Sun intensity */
static double _g = 0.76; /* Mean cosine */ static double _g = 0.76; /* Mean cosine */
#endif
/*typedef struct /*typedef struct
{ {

View file

@ -1,5 +1,7 @@
#include "system.h" #include "system.h"
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include "IL/il.h" #include "IL/il.h"
#include "IL/ilu.h" #include "IL/ilu.h"

View file

@ -51,16 +51,12 @@ TerrainDefinition terrainCreateDefinition()
void terrainDeleteDefinition(TerrainDefinition* definition) void terrainDeleteDefinition(TerrainDefinition* definition)
{ {
int i;
noiseDeleteGenerator(definition->height_noise); noiseDeleteGenerator(definition->height_noise);
layersDelete(definition->canvases); layersDelete(definition->canvases);
} }
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination) void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
{ {
int i;
noiseCopy(source->height_noise, destination->height_noise); noiseCopy(source->height_noise, destination->height_noise);
destination->height_factor = source->height_factor; destination->height_factor = source->height_factor;
destination->scaling = source->scaling; destination->scaling = source->scaling;
@ -335,7 +331,7 @@ double terrainGetHeightNormalized(TerrainDefinition* definition, double x, doubl
} }
else else
{ {
return _getHeight(definition, x, z) - definition->_min_height / (definition->_max_height - definition->_min_height); return (_getHeight(definition, x, z) - definition->_min_height) / (definition->_max_height - definition->_min_height);
} }
} }

View file

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h>
TerrainCanvas* terrainCanvasCreate() TerrainCanvas* terrainCanvasCreate()
{ {
@ -108,7 +109,7 @@ void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas)
double terrainCanvasGetLimits(TerrainCanvas* canvas, double* ymin, double* ymax) double terrainCanvasGetLimits(TerrainCanvas* canvas, double* ymin, double* ymax)
{ {
return heightmapGetLimits(canvas->height_map, ymin, ymax); return heightmapGetLimits(&canvas->height_map, ymin, ymax);
} }
void terrainCanvasRevertToTerrain(TerrainCanvas* canvas, TerrainDefinition* terrain, int only_masked) void terrainCanvasRevertToTerrain(TerrainCanvas* canvas, TerrainDefinition* terrain, int only_masked)