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:
parent
3ad79c9b7c
commit
fe561c2062
7 changed files with 80 additions and 18 deletions
3
TODO
3
TODO
|
@ -22,9 +22,6 @@ Technology Preview 2 :
|
|||
=> Add curve modes
|
||||
=> Add logarithmic mode
|
||||
=> 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).
|
||||
- Find a new licence.
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ public:
|
|||
{
|
||||
_preview->commitChunkTransaction(&pixbuf, _xstart, _ystart, _xsize, _ysize, revision);
|
||||
}
|
||||
else
|
||||
{
|
||||
_preview->rollbackChunkTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
|
@ -194,6 +198,23 @@ void PreviewDrawingManager::removeChunks(BasePreview* preview)
|
|||
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)
|
||||
{
|
||||
for (int i = 0; i < _chunks.size(); i++)
|
||||
|
@ -293,6 +314,8 @@ QWidget(parent)
|
|||
_width = width();
|
||||
_height = height();
|
||||
_revision = 0;
|
||||
_transactions_count = 0;
|
||||
_redraw_requested = false;
|
||||
|
||||
_info = new QLabel(this);
|
||||
_info->setVisible(false);
|
||||
|
@ -301,11 +324,12 @@ QWidget(parent)
|
|||
this->alive = true;
|
||||
|
||||
QObject::connect(this, SIGNAL(contentChange()), this, SLOT(update()));
|
||||
QObject::connect(this, SIGNAL(redrawRequested()), this, SLOT(handleRedraw()));
|
||||
|
||||
this->setMinimumSize(256, 256);
|
||||
this->setMaximumSize(256, 256);
|
||||
this->resize(256, 256);
|
||||
|
||||
startTimer(50);
|
||||
}
|
||||
|
||||
BasePreview::~BasePreview()
|
||||
|
@ -440,18 +464,31 @@ void BasePreview::toggleChangeEvent(QString, bool)
|
|||
|
||||
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 result;
|
||||
|
||||
_lock_drawing->lock();
|
||||
|
||||
*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();
|
||||
|
||||
if (revision == _revision)
|
||||
{
|
||||
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();
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
_transactions_count--;
|
||||
|
||||
_lock_drawing->unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void BasePreview::rollbackChunkTransaction()
|
||||
{
|
||||
_lock_drawing->lock();
|
||||
|
||||
_transactions_count--;
|
||||
|
||||
_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);
|
||||
}
|
||||
|
||||
void BasePreview::handleRedraw()
|
||||
void BasePreview::timerEvent(QTimerEvent*)
|
||||
{
|
||||
_lock_drawing->lock();
|
||||
|
||||
if (_redraw_requested && _transactions_count == 0)
|
||||
{
|
||||
updateData();
|
||||
invalidatePixbuf(128);
|
||||
_redraw_requested = false;
|
||||
}
|
||||
|
||||
_lock_drawing->unlock();
|
||||
}
|
||||
|
|
|
@ -44,7 +44,8 @@ public:
|
|||
void redraw();
|
||||
|
||||
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);
|
||||
|
||||
|
@ -72,6 +73,7 @@ private:
|
|||
void updateChunks();
|
||||
void invalidatePixbuf(int value);
|
||||
|
||||
void timerEvent(QTimerEvent* event);
|
||||
void showEvent(QShowEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void paintEvent(QPaintEvent* event);
|
||||
|
@ -94,6 +96,8 @@ private:
|
|||
int _height;
|
||||
|
||||
int _revision;
|
||||
int _transactions_count;
|
||||
bool _redraw_requested;
|
||||
|
||||
int mousex;
|
||||
int mousey;
|
||||
|
@ -120,7 +124,6 @@ signals:
|
|||
void redrawRequested();
|
||||
|
||||
private slots:
|
||||
void handleRedraw();
|
||||
void choiceSelected(QAction* action);
|
||||
};
|
||||
|
||||
|
@ -153,6 +156,7 @@ public:
|
|||
void addChunk(PreviewChunk* chunk);
|
||||
void removeChunks(BasePreview* preview);
|
||||
void updateChunks(BasePreview* preview);
|
||||
void suspendChunks(BasePreview* preview);
|
||||
void updateAllChunks();
|
||||
void performOneThreadJob();
|
||||
int chunkCount();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#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 _betaM = {21e-6, 0.0, 0.0}; /* Mie scattering coefficients at sea level */
|
||||
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 _sunIntensity = 20.0; /* Sun intensity */
|
||||
static double _g = 0.76; /* Mean cosine */
|
||||
#endif
|
||||
|
||||
/*typedef struct
|
||||
{
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "system.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "IL/il.h"
|
||||
#include "IL/ilu.h"
|
||||
|
|
|
@ -51,16 +51,12 @@ TerrainDefinition terrainCreateDefinition()
|
|||
|
||||
void terrainDeleteDefinition(TerrainDefinition* definition)
|
||||
{
|
||||
int i;
|
||||
|
||||
noiseDeleteGenerator(definition->height_noise);
|
||||
layersDelete(definition->canvases);
|
||||
}
|
||||
|
||||
void terrainCopyDefinition(TerrainDefinition* source, TerrainDefinition* destination)
|
||||
{
|
||||
int i;
|
||||
|
||||
noiseCopy(source->height_noise, destination->height_noise);
|
||||
destination->height_factor = source->height_factor;
|
||||
destination->scaling = source->scaling;
|
||||
|
@ -335,7 +331,7 @@ double terrainGetHeightNormalized(TerrainDefinition* definition, double x, doubl
|
|||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
TerrainCanvas* terrainCanvasCreate()
|
||||
{
|
||||
|
@ -108,7 +109,7 @@ void terrainCanvasLoad(PackStream* stream, TerrainCanvas* canvas)
|
|||
|
||||
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)
|
||||
|
|
Loading…
Reference in a new issue